/* Bringing a customer's own domain on board: one view, shown to the domain's owner in
   the app (My domain > Setup) and to admins in the console (Domains > a domain).
   It reads domain_progress() and shows where the domain is on the way from request to
   live, with the DNS records to publish and whether each one has been found.

   Props: id            the domain's id
          load()        -> Promise of domain_progress(id)
          check()       -> Promise of a fresh DNS report (POST /api/domains/check)
          actions       optional node shown inside the step that is waiting on an admin
          onPeople()    optional: jump to the People tab                                */
(function () {
  const { useState, useEffect, useCallback } = React;
  const when = (iso) => iso ? new Date(iso).toLocaleDateString(undefined, { day: "numeric", month: "short", year: "numeric" }) : "";
  const ago = (iso) => { if (!iso) return "never"; const m = Math.round((Date.now() - new Date(iso)) / 60000); return m < 1 ? "just now" : m < 60 ? `${m} min ago` : m < 1440 ? `${Math.round(m / 60)} h ago` : when(iso); };
  const WORD = { ok: "Published", missing: "Not found", doubled: "Wrong host", different: "Different", conflict: "Conflict", error: "Not checked" };

  function Copy({ text }) {
    const [done, setDone] = useState(false);
    return <button className="setup-copy" onClick={async () => { try { await navigator.clipboard.writeText(text); setDone(true); setTimeout(() => setDone(false), 1500); } catch {} }}>{done ? "Copied" : "Copy"}</button>;
  }

  function Records({ list }) {
    return (<div className="setup-recs">{list.map((r, i) => (<div key={i} className={"setup-rec s-" + r.status}>
      <div className="setup-rec-top"><b>{r.label}</b><span className={"setup-chip s-" + r.status}>{WORD[r.status] || r.status}</span></div>
      <dl>
        <dt>Type</dt><dd>{r.type}</dd>
        <dt>Host</dt><dd><code>{r.host}</code> <Copy text={r.host} /></dd>
        <dt>Value</dt><dd><code>{r.value}</code> <Copy text={r.value} /></dd>
      </dl>
      {r.status !== "ok" && <p className="setup-hint">{r.hint}</p>}
    </div>))}</div>);
  }

  function Setup({ id, load, check, actions, onPeople }) {
    const [p, setP] = useState(null); const [err, setErr] = useState(""); const [busy, setBusy] = useState(false);
    const refresh = useCallback(async () => { try { setP(await load()); setErr(""); } catch (e) { setErr(e.message || "Couldn't load this domain."); } }, [id]);
    useEffect(() => { setP(null); refresh(); }, [refresh]);
    const run = async () => { setBusy(true); try { await check(); await refresh(); } catch (e) { setErr(e.message || "The check couldn't run."); } finally { setBusy(false); } };
    if (err && !p) return <p className="setup-hint">{err}</p>;
    if (!p) return <p className="muted">Loading…</p>;

    const dns = p.dns, recs = (dns && dns.records) || [];
    const main = recs.filter((r) => r.role !== "extra"), extra = recs.filter((r) => r.role === "extra");
    const approved = p.status !== "pending", failed = p.job && p.job.status === "failed";
    const live = !!(dns && dns.mx_ok), sending = !!(dns && dns.sending_ok);
    // each step: done | now | problem | later
    const s1 = "done";
    const s2 = approved ? "done" : "now";
    const s3 = p.on_mail_server ? "done" : failed ? "problem" : approved ? "now" : "later";
    const s4 = live ? "done" : p.on_mail_server ? (dns && ["conflict", "different", "doubled"].includes(dns.mx_status) ? "problem" : "now") : "later";
    const s5 = p.accounts > 0 ? "done" : live ? "now" : "later";
    const Step = ({ n, state, title, children }) => (<li className={"setup-step st-" + state}>
      <span className="setup-mark" aria-hidden="true">{state === "done" ? "✓" : state === "problem" ? "!" : n}</span>
      <div><h4>{title}<span className="sr-only"> ({state === "done" ? "done" : state === "now" ? "in progress" : state === "problem" ? "needs attention" : "not started"})</span></h4>{children}</div></li>);

    const dnsBlock = (<>
      {recs.length === 0
        ? <p className="muted">{p.on_mail_server ? "The records haven't been checked yet." : "The records to publish appear here once the domain is set up on the mail server."}</p>
        : <>
          <p className="muted" style={{ margin: "0 0 8px" }}>Add these at the company that hosts {p.name}'s DNS. Enter the <b>Host</b> exactly as shown: most DNS hosts add “.{p.name}” for you, and typing it yourself puts the record in the wrong place.</p>
          <Records list={main} />
          {extra.length > 0 && <details className="setup-more"><summary>Optional records ({extra.filter((r) => r.status === "ok").length} of {extra.length} published)</summary><Records list={extra} /></details>}
        </>}
      {p.on_mail_server && <div className="setup-check"><button className="btn btn-quiet" onClick={run} disabled={busy}>{busy ? "Checking…" : "Check again"}</button>
        <span className="muted">Last checked {ago(p.dns_checked_at)}. Popitron also checks by itself every half hour.</span></div>}
      {err && <p className="setup-hint">{err}</p>}
    </>);

    if (p.home) return (<div className="setup"><p className="muted" style={{ marginTop: 0 }}>Popitron's own domain. These are the records the mail server expects for it.</p>{dnsBlock}</div>);

    return (<div className="setup">
      <p className={"setup-status" + (live ? " is-live" : "")}>{p.status === "suspended" ? <>This domain is <b>deactivated</b>. Its mailboxes are paused.</>
        : live ? <><b>{p.name} is live.</b> Its mail comes through Popitron.{!sending && " Some records for sending are still to publish."}</>
        : <><b>{p.name} isn't live yet.</b> Mail for it still goes wherever its MX record points today.</>}</p>
      <ol className="setup-steps">
        <Step n="1" state={s1} title="Requested">
          <p>{p.owner || "Someone"} asked for {p.name} on {when(p.requested_at)}.{p.is_admin && !p.owner_plan_business ? ` Their plan (${p.owner_plan || "none"}) doesn't include their own domain.` : p.owner_plan ? ` Plan: ${p.owner_plan}.` : ""}</p>
        </Step>
        <Step n="2" state={s2} title="Approved by Popitron">
          {approved ? <p>Approved {when(p.activated_at)}.</p> : p.is_admin ? <p>Approve it to set the domain up on the mail server.</p> : <p>Waiting for Popitron to approve the request. You'll get an email, and the next step appears here.</p>}
          {!approved && actions}
        </Step>
        <Step n="3" state={s3} title="Set up on the mail server">
          {p.on_mail_server ? <p>Done. The domain has its own signing keys.</p>
            : failed ? <><p>{p.is_admin ? `It failed after ${p.job.attempts} tries: ${p.job.error || "no reason given"}` : "Something went wrong on our side while setting this up. We've been told, and there's nothing you need to do."}</p>{actions}</>
            : approved ? <p>In progress. This normally takes under a minute.</p> : <p className="muted">After approval.</p>}
        </Step>
        <Step n="4" state={s4} title={`Point ${p.name} at Popitron`}>
          {live && <p>The MX record points at Popitron. {sending ? "Everything needed for sending is published too." : "Publish the rest so that mail you send is trusted by other providers."}</p>}
          {s4 !== "later" ? dnsBlock : <p className="muted">The records to publish appear once the domain is set up.</p>}
        </Step>
        <Step n="5" state={s5} title="Add your people">
          <p>{p.accounts} of {p.max_accounts} accounts created.{p.accounts === 0 ? " Each person gets a mailbox at this domain and their own White, Black and Grey lists." : ""}</p>
          {onPeople && approved && <button className="btn btn-quiet" onClick={onPeople}>Manage accounts</button>}
        </Step>
      </ol>
    </div>);
  }
  window.PopDomainSetup = Setup;
})();
