// =================================================================
// pw-screens-op-leads.jsx — Operator · Marketing-site enquiries
//
// The inbox for the "book a walkthrough" modal on dropcap.krafts.ai.
//
// Not the same thing as the publisher's Content Leads screen (#/content-leads), which is a
// publisher-role screen showing readers who filled in a form on that publisher's own content — it
// reads /v1/content-leads with a publisher token, so an operator cannot see it as themselves at
// all. These enquiries belong to DropCap, have no publisher, and nobody is charged for them.
//
// Deliberately a worklist rather than a CRM: a lead has one status, one note, and a person working
// down the list. Everything past that belongs in whatever the sales tool eventually is.
//
// The list is a standard DataTable like every other list in the product. It was hand-rolled stacked
// rows first, which meant no sorting, no pagination and column alignment that matched nothing else
// on screen. The cost of the table is that a lead has more fields than a row can carry, so the row
// holds what you scan by and clicking it opens the rest.
// =================================================================

const LEAD_STATUSES = ["new", "contacted", "qualified", "closed", "spam"];

const LEAD_TONE = {
  new: "accent",
  contacted: "info",
  qualified: "good",
  closed: "neutral",
  spam: "warn",
};

// The detail the row cannot hold: the note they typed, and the status controls.
const LeadDetail = ({ lead, onClose, onChanged, notify }) => {
  const [note, setNote] = React.useState((lead && lead.handled_note) || "");
  const [busy, setBusy] = React.useState(false);
  React.useEffect(() => { setNote((lead && lead.handled_note) || ""); }, [lead && lead.lead_id]);
  if (!lead) return null;

  const setStatus = async (status) => {
    setBusy(true);
    try {
      // No optimistic update (the `null` second argument): the row is re-fetched on success, and
      // an optimistic status flip that later rolls back reads as the button having done nothing.
      await window.__api.write("adminUpdateMarketingLead", null, {
        params: { lead_id: lead.lead_id },
        body: { status, handled_note: note || null },
      });
      notify(`Marked ${status}.`, "good");
      onChanged();
      onClose();
    } catch (e) {
      notify((e && e.message) || "Could not update that lead.", "bad");
    } finally {
      setBusy(false);
    }
  };

  const Row = ({ label, children }) => (
    <div style={{ display: "flex", gap: 12, padding: "7px 0", borderBottom: "1px solid var(--line-2)" }}>
      <span style={{ minWidth: 104, fontSize: 12.5, color: "var(--muted)" }}>{label}</span>
      <span style={{ fontSize: 13.5, color: "var(--ink-2)", wordBreak: "break-word" }}>{children}</span>
    </div>
  );

  return (
    <Modal open={!!lead} onClose={onClose} title={lead.name} width={560}>
      <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
        {/* mailto rather than a copy button: the next action on every one of these is an email. */}
        <Row label="Email"><a href={`mailto:${lead.email}`} style={{ color: "var(--accent-strong)" }}>{lead.email}</a></Row>
        <Row label="Organisation">{lead.org}</Row>
        <Row label="Interest">{lead.intent}</Row>
        {lead.scale ? <Row label="Scale">{lead.scale}</Row> : null}
        {lead.goal ? <Row label="Goal">{lead.goal}</Row> : null}
        <Row label="Received">{fmt.dateTime(lead.created_at)}</Row>
        <Row label="Came from">{[lead.source_page, lead.country].filter(Boolean).join(" · ") || "—"}</Row>
        {lead.handled_at ? <Row label="Last actioned">{fmt.dateTime(lead.handled_at)}</Row> : null}
      </div>

      {lead.note ? (
        <div style={{ marginTop: 14 }}>
          <div style={{ fontSize: 12.5, color: "var(--muted)", marginBottom: 6 }}>What they wrote</div>
          <div style={{ fontSize: 13.5, lineHeight: 1.55, color: "var(--ink-2)", whiteSpace: "pre-wrap", background: "var(--panel-2)", border: "1px solid var(--line-2)", borderRadius: 8, padding: "9px 11px" }}>
            {lead.note}
          </div>
        </div>
      ) : null}

      <div style={{ marginTop: 16, display: "flex", flexDirection: "column", gap: 9 }}>
        <div style={{ fontSize: 12.5, color: "var(--muted)" }}>Internal note</div>
        <textarea rows={2} value={note} onChange={(e) => setNote(e.target.value)}
          placeholder="What happened — who replied, what was agreed."
          style={{ font: "inherit", fontSize: 13.5, padding: "9px 11px", border: "1px solid var(--line)", borderRadius: 8, background: "var(--panel)", color: "var(--ink)", resize: "vertical" }} />
        <div style={{ display: "flex", flexWrap: "wrap", gap: 8, alignItems: "center" }}>
          <span style={{ fontSize: 12.5, color: "var(--muted)" }}>Mark as</span>
          {LEAD_STATUSES.filter((s) => s !== lead.status).map((s) => (
            <Btn key={s} kind="secondary" size="sm" disabled={busy} onClick={() => setStatus(s)}>{s}</Btn>
          ))}
        </div>
      </div>
    </Modal>
  );
};

const OpLeadsScreen = ({ data, setData }) => {
  const notify = (msg, tone) => (window.__toast ? window.__toast(msg, tone) : null);
  const [filter, setFilter] = React.useState("new");
  const [openId, setOpenId] = React.useState(null);

  const reload = React.useCallback((status) => {
    const q = status && status !== "all" ? { status } : {};
    return window.__api
      .read("adminListMarketingLeads", { query: q })
      .then((r) => setData((d) => ({ ...d, marketingLeads: r })))
      .catch(() => notify("Could not load enquiries.", "bad"));
  }, [setData]);

  React.useEffect(() => { reload(filter); }, [filter, reload]);

  const payload = (data && data.marketingLeads) || null;
  const leads = (payload && payload.leads) || [];
  const counts = (payload && payload.counts) || { new: 0, contacted: 0, qualified: 0, closed: 0, spam: 0 };
  const openLead = leads.find((l) => l.lead_id === openId) || null;

  const columns = [
    {
      key: "created_at", label: "Received",
      render: (r) => <span style={{ fontFamily: "var(--mono)", fontSize: 12.5, color: "var(--muted)" }}>{fmt.dateTime(r.created_at)}</span>,
    },
    {
      key: "name", label: "Name",
      render: (r) => <strong style={{ color: "var(--ink)" }}>{r.name}</strong>,
    },
    { key: "org", label: "Organisation" },
    {
      key: "email", label: "Email",
      // stopPropagation so opening the mail client does not also open the detail modal behind it.
      render: (r) => (
        <a href={`mailto:${r.email}`} onClick={(e) => e.stopPropagation()} style={{ color: "var(--accent-strong)" }}>{r.email}</a>
      ),
    },
    {
      key: "intent", label: "Interest",
      render: (r) => <Pill tone={r.intent === "advertiser" ? "warn" : "accent"}>{r.intent}</Pill>,
    },
    {
      key: "source_page", label: "Source",
      render: (r) => (
        <span style={{ fontSize: 12.5, color: "var(--muted-2)" }}>
          {[r.source_page, r.country].filter(Boolean).join(" · ") || "—"}
        </span>
      ),
    },
    {
      key: "status", label: "Status",
      render: (r) => <Pill tone={LEAD_TONE[r.status] || "neutral"}>{r.status}</Pill>,
    },
  ];

  return (
    <Screen>
      <PageHead icon={IconUsers} title="Marketing enquiries"
        subtitle="The lead modal on the public site. DropCap's own enquiries, not any publisher's." />

      <KpiGrid>
        <StatCard label="New" value={counts.new} sub="unworked" icon={<IconActivity size={16}/>}/>
        <StatCard label="Contacted" value={counts.contacted} sub="in flight" icon={<IconUsers size={16}/>}/>
        <StatCard label="Qualified" value={counts.qualified} sub="worth a call" icon={<IconRocket size={16}/>}/>
        <StatCard label="Spam" value={counts.spam} sub="rejected by hand" icon={<IconStore size={16}/>}/>
      </KpiGrid>

      {/* The form's only real defence is Turnstile, and verifyTurnstile fails open when the secret
          is unset. A silent fail-open has to be visible somewhere, and this is that somewhere. */}
      {payload && payload.turnstile_configured === false && (
        <div style={{ fontSize: 13, lineHeight: 1.55, color: "var(--warn)", background: "var(--warn-soft)", border: "1px solid var(--line)", borderRadius: 9, padding: "10px 13px" }}>
          <strong>Turnstile is not configured.</strong> The public form is accepting submissions
          without a challenge — only the per-IP rate limit and the honeypot are in front of it. Set
          <code style={{ fontFamily: "var(--mono)" }}> TURNSTILE_SECRET_KEY </code>
          on the API Worker and the site key in <code style={{ fontFamily: "var(--mono)" }}>dropcap-site-config.js</code>.
        </div>
      )}

      <Card
        title="Enquiries"
        subtitle="Newest first. Select a row to read the enquiry and change its status."
        padded={false}
        action={
          <select value={filter} onChange={(e) => setFilter(e.target.value)}
            style={{ font: "inherit", fontSize: 13, padding: "6px 10px", borderRadius: 8, border: "1px solid var(--line)", background: "var(--panel)", color: "var(--ink)" }}>
            <option value="all">All</option>
            {LEAD_STATUSES.map((s) => <option key={s} value={s}>{s}</option>)}
          </select>
        }
      >
        <DataTable
          rows={leads}
          keyField="lead_id"
          columns={columns}
          defaultSort={{ key: "created_at", dir: "desc" }}
          rowsPerPage={25}
          stickyHeader
          onRowClick={(r) => setOpenId(r.lead_id)}
          empty={filter === "all" ? "No enquiries yet." : `Nothing ${filter}.`}
        />
      </Card>

      <LeadDetail
        lead={openLead}
        onClose={() => setOpenId(null)}
        onChanged={() => reload(filter)}
        notify={notify}
      />
    </Screen>
  );
};
