// =================================================================
// pw-screens-op-pricing.jsx — Operator · Industry segments and Campaign minimums (payments phase 4,
// migration 0057).
//
// Both are platform pricing, not tenant data: every staff member can read them; only a superadmin can
// change them. The API gates the writes on the destructive capability, which a manager does not hold,
// so a manager's click is refused with a 403 rather than half-applied — the page says so up front.
//
// Minimums are never edited. A change is a new row with its own effective date, and every campaign
// already priced keeps the row it was priced against — so the table shows the history (in force,
// scheduled, superseded) rather than one editable number per key.
// =================================================================

const pricingNotify = (msg, tone) => (window.__toast ? window.__toast(msg, tone) : null);

const PricingAccessNote = () => (
  <Banner tone="info" icon={<IconInfo size={15}/>}>
    Superadmin only: managers can view segments and minimums but cannot change them.
  </Banner>
);

// ---------------------------------------------------------------------------
// Industry segments
// ---------------------------------------------------------------------------

const SegmentRenameModal = ({ segment, onClose, onSaved }) => {
  const [name, setName] = React.useState("");
  React.useEffect(() => { setName(segment ? segment.name : ""); }, [segment && segment.segment_id]);
  if (!segment) return null;
  const save = async () => {
    try {
      await window.__api.write("adminUpdateIndustrySegment",
        (d) => ({ ...d, industrySegments: (d.industrySegments || []).map((s) => s.segment_id === segment.segment_id ? { ...s, name: name.trim() } : s) }),
        { params: { segment_id: segment.segment_id }, body: { name: name.trim() }, ok: "Segment renamed", err: "Couldn’t rename the segment" });
      onSaved(); onClose();
    } catch (e) { /* write() has already said why */ }
  };
  return (
    <Modal open onClose={onClose} title={`Rename · ${segment.name}`} width={440}
      footer={<><Btn kind="secondary" onClick={onClose}>Cancel</Btn><Btn kind="primary" disabled={!name.trim() || name.trim() === segment.name} onClick={save}>Save</Btn></>}>
      <FormField label="Name" hint="Campaigns and brands keep pointing at the segment; only the label changes.">
        <Input value={name} onChange={(e) => setName(e.target.value)}/>
      </FormField>
    </Modal>
  );
};

const OpSegmentsScreen = ({ data }) => {
  const [renaming, setRenaming] = React.useState(null);
  const list = useListQuery("adminListIndustrySegments", { sort: "name", dir: "asc", filters: { status: "" }, watch: data.industrySegments });
  React.useEffect(() => { if (list.error) pricingNotify("Could not load segments.", "bad"); }, [list.error]);

  const setStatus = async (row, status) => {
    try {
      await window.__api.write("adminUpdateIndustrySegment",
        (d) => ({ ...d, industrySegments: (d.industrySegments || []).map((s) => s.segment_id === row.segment_id
          ? { ...s, status, retired_at: status === "retired" ? new Date().toISOString() : null } : s) }),
        { params: { segment_id: row.segment_id }, body: { status }, ok: status === "retired" ? "Segment retired" : "Segment reinstated", err: "Couldn’t change the segment" });
      list.reload();
    } catch (e) { /* write() has already said why */ }
  };

  return (
    <Screen>
      <PageHead icon={IconTag} title="Industry segments"
        subtitle="What a brand and its campaigns sell. Minimums are set per segment."
        actions={<Btn kind="primary" size="sm" onClick={() => window.__nav("segment-create")}>Add segment</Btn>}/>
      <PricingAccessNote/>
      <Card title="Segments" subtitle="Retiring a segment keeps it on every campaign and brand that uses it; it just cannot be chosen again." padded={false}>
        <div style={{ padding: "12px 16px", borderBottom: "1px solid var(--line-2)" }}>
          <ListToolbar list={list} placeholder="Search name or code"
            filters={[{ key: "status", label: "Statuses", options: statusOptions(["active", "retired"]) }]}/>
        </div>
        <DataTable rows={list.rows} keyField="segment_id" server={list.server} empty="No segments yet."
          columns={[
            { key: "name", label: "Name", sortable: true, render: (r) => <strong style={{ color: "var(--ink)" }}>{r.name}</strong> },
            { key: "code", label: "Code", render: (r) => <span style={{ fontFamily: "var(--mono)", fontSize: 12.5 }}>{r.code}</span> },
            { key: "status", label: "Status", sortable: true, render: (r) => <StatusPill status={r.status}/> },
            { key: "retired_at", label: "Retired", render: (r) => <span style={{ fontSize: 12.5, color: "var(--muted)" }}>{r.retired_at ? fmt.date(r.retired_at) : "—"}</span> },
            {
              key: "actions", label: "",
              render: (r) => (
                <div style={{ display: "flex", gap: 6, justifyContent: "flex-end" }}>
                  <Btn kind="secondary" size="sm" onClick={(e) => { e.stopPropagation(); setRenaming(r); }}>Rename</Btn>
                  <Btn kind="secondary" size="sm" onClick={(e) => { e.stopPropagation(); setStatus(r, r.status === "active" ? "retired" : "active"); }}>
                    {r.status === "active" ? "Retire" : "Reinstate"}
                  </Btn>
                </div>
              ),
            },
          ]}/>
      </Card>
      <SegmentRenameModal segment={renaming} onClose={() => setRenaming(null)} onSaved={list.reload}/>
    </Screen>
  );
};

const segmentCode = (name) => name.toLowerCase().normalize("NFKD").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 63);

const SegmentCreateScreen = () => {
  const [f, setF] = React.useState({ name: "", code: "" });
  const [busy, setBusy] = React.useState(false);
  const code = f.code.trim() || segmentCode(f.name);
  const codeOk = /^[a-z0-9][a-z0-9_-]{0,62}$/.test(code);
  const save = async () => {
    setBusy(true);
    try {
      const segment_id = "seg_" + Math.random().toString(36).slice(2, 8);
      await window.__api.write("adminCreateIndustrySegment",
        (d) => ({ ...d, industrySegments: [...(d.industrySegments || []), { segment_id, code, name: f.name.trim(), status: "active", retired_at: null, created_at: new Date().toISOString(), updated_at: new Date().toISOString() }] }),
        { body: { name: f.name.trim(), ...(f.code.trim() ? { code: f.code.trim() } : {}) }, ok: `Added ${f.name.trim()}`, err: "Couldn’t add that segment" });
      pwListsStale();
      window.__nav("op-segments");
    } catch (e) { /* write() has already said why */ } finally { setBusy(false); }
  };
  return (
    <FormFrame page={{ icon: IconTag, back: "Industry segments" }} kind="modal" open onClose={pwBackTo("op-segments")} title="Add segment" width={480}
      footer={<><Btn kind="secondary" onClick={pwBackTo("op-segments")}>Cancel</Btn><Btn kind="primary" disabled={!f.name.trim() || !codeOk || busy} onClick={save}>{busy ? "Adding…" : "Add segment"}</Btn></>}>
      <FormField label="Name"><Input value={f.name} onChange={(e) => setF({ ...f, name: e.target.value })} placeholder="Financial services"/></FormField>
      <FormField label="Code" hint="Stable identifier; derived from the name when left blank. Renaming later never changes it.">
        <Input value={f.code} onChange={(e) => setF({ ...f, code: e.target.value.toLowerCase() })} placeholder={segmentCode(f.name) || "financial-services"}/>
      </FormField>
    </FormFrame>
  );
};

// ---------------------------------------------------------------------------
// Campaign minimums
// ---------------------------------------------------------------------------

const MIN_STATE_TONE = { in_force: "good", scheduled: "accent", superseded: "neutral" };

const OpMinimumsScreen = ({ data }) => {
  useRefList(["adminListIndustrySegments"]);
  const list = useListQuery("adminListCampaignMinimums", { sort: "effective_from", dir: "desc", filters: { pricing_model: "", currency: "", segment_id: "" }, watch: data.campaignMinimums });
  React.useEffect(() => { if (list.error) pricingNotify("Could not load minimums.", "bad"); }, [list.error]);
  const segName = (id) => (data.industrySegments || []).find((s) => s.segment_id === id)?.name;
  return (
    <Screen>
      <PageHead icon={IconSliders} title="Campaign minimums"
        subtitle="Brand-side floors per industry segment × reader country × campaign type. The publisher's share is unchanged."
        actions={<Btn kind="primary" size="sm" onClick={() => window.__nav("minimum-create")}>Add minimum</Btn>}/>
      <PricingAccessNote/>
      <Banner tone="info" icon={<IconInfo size={15}/>}>
        A minimum is never edited. A new row takes over from its effective date; campaigns already priced keep the row
        they were priced against. Where no segment × country row exists, the default row (every segment, every country) applies.
      </Banner>
      <Card title="Minimums" padded={false}>
        <div style={{ padding: "12px 16px", borderBottom: "1px solid var(--line-2)" }}>
          <ListToolbar list={list} placeholder="Search country or note"
            filters={[
              { key: "pricing_model", label: "Types", options: [{ label: "CPC", value: "cpc" }, { label: "CPA", value: "cpa" }] },
              { key: "currency", label: "Currencies", options: PW_CAMPAIGN_CURRENCIES.map((c) => ({ label: c, value: c })) },
              { key: "segment_id", label: "Segments", options: (data.industrySegments || []).map((s) => ({ label: s.name, value: s.segment_id })) },
            ]}/>
        </div>
        <DataTable rows={list.rows} keyField="minimum_id" server={list.server} empty="No minimums match."
          columns={[
            { key: "segment", label: "Segment", render: (r) => r.segment_id ? (r.segment_name || segName(r.segment_id) || "—") : <span style={{ color: "var(--muted)" }}>Every segment</span> },
            { key: "country", label: "Reader country", render: (r) => r.country || <span style={{ color: "var(--muted)" }}>Every country</span> },
            { key: "pricing_model", label: "Type", render: (r) => String(r.pricing_model).toUpperCase() },
            { key: "min_bid", label: "Min bid", sortable: true, align: "right", render: (r) => pwMinMoney(r.min_bid, r.currency) },
            { key: "min_campaign_budget", label: "Min budget", align: "right", render: (r) => pwMinMoney(r.min_campaign_budget, r.currency) },
            { key: "min_topup", label: "Min top-up", align: "right", render: (r) => pwMinMoney(r.min_topup, r.currency) },
            { key: "effective_from", label: "From", sortable: true, render: (r) => <span style={{ fontFamily: "var(--mono)", fontSize: 12.5 }}>{fmt.date(r.effective_from)}</span> },
            { key: "state", label: "State", render: (r) => <Pill tone={MIN_STATE_TONE[r.state] || "neutral"}>{String(r.state || "").replace("_", " ")}</Pill> },
            { key: "note", label: "Note", render: (r) => <span style={{ fontSize: 12.5, color: "var(--muted)" }}>{r.note || ""}</span> },
          ]}/>
      </Card>
    </Screen>
  );
};

const MinimumCreateScreen = ({ data }) => {
  useRefList(["adminListIndustrySegments"]);
  const [f, setF] = React.useState({ segment_id: "", country: "", pricing_model: "cpc", currency: "USD", min_bid: "", min_campaign_budget: "", min_topup: "", effective_from: "", note: "" });
  const [busy, setBusy] = React.useState(false);
  const set = (p) => setF((x) => ({ ...x, ...p }));
  const segs = (data.industrySegments || []);
  const n = (v) => (v === "" ? NaN : Number(v));
  const countryOk = !f.country || /^[A-Z]{2}$/.test(f.country);
  const future = f.effective_from ? new Date(f.effective_from) : null;
  const dateOk = !future || future.getTime() >= Date.now() - 60_000;
  const canSave = n(f.min_bid) > 0 && n(f.min_campaign_budget) >= 0 && n(f.min_topup) >= 0 && countryOk && dateOk && !busy;
  const save = async () => {
    setBusy(true);
    const body = {
      ...(f.segment_id ? { segment_id: f.segment_id } : {}),
      ...(f.country ? { country: f.country } : {}),
      pricing_model: f.pricing_model, currency: f.currency,
      min_bid: n(f.min_bid), min_campaign_budget: n(f.min_campaign_budget), min_topup: n(f.min_topup),
      ...(future ? { effective_from: future.toISOString() } : {}),
      ...(f.note.trim() ? { note: f.note.trim() } : {}),
    };
    const eff = future ? future.toISOString() : new Date().toISOString();
    const scheduled = Boolean(future && future.getTime() > Date.now());
    const key = (r) => `${r.segment_id || "*"}|${r.country || "*"}|${r.pricing_model}|${r.currency}`;
    const row = { minimum_id: "min_" + Math.random().toString(36).slice(2, 8), segment_id: f.segment_id || null, segment_name: segs.find((s) => s.segment_id === f.segment_id)?.name || null,
      country: f.country || null, pricing_model: f.pricing_model, currency: f.currency, min_bid: body.min_bid, min_campaign_budget: body.min_campaign_budget, min_topup: body.min_topup,
      effective_from: eff, note: body.note || null, created_by: "you", created_at: new Date().toISOString(), state: scheduled ? "scheduled" : "in_force" };
    try {
      await window.__api.write("adminCreateCampaignMinimum",
        // Demo: the new in-force row supersedes the previous one on its key; nothing is edited.
        (d) => ({ ...d, campaignMinimums: [row, ...(d.campaignMinimums || []).map((r) => (!scheduled && r.state === "in_force" && key(r) === key(row) ? { ...r, state: "superseded" } : r))] }),
        { body, ok: scheduled ? "Minimum scheduled" : "Minimum in force", err: "Couldn’t add that minimum" });
      pwListsStale();
      window.__nav("op-minimums");
    } catch (e) { /* write() has already said why */ } finally { setBusy(false); }
  };
  return (
    <FormFrame page={{ icon: IconSliders, back: "Campaign minimums" }} kind="modal" open onClose={pwBackTo("op-minimums")} title="Add minimum" width={560}
      footer={<><Btn kind="secondary" onClick={pwBackTo("op-minimums")}>Cancel</Btn><Btn kind="primary" disabled={!canSave} onClick={save}>{busy ? "Saving…" : "Add minimum"}</Btn></>}>
      <FieldGroup cols={2}>
        <FormField label="Industry segment">
          <Select value={f.segment_id} onChange={(v) => set({ segment_id: v })}
            options={[{ label: "Every segment (default)", value: "" }, ...segs.map((s) => ({ label: s.status === "retired" ? `${s.name} (retired)` : s.name, value: s.segment_id }))]}/>
        </FormField>
        <FormField label="Reader country" hint="Where the ad is shown. Blank: every country.">
          <Input value={f.country} maxLength={2} placeholder="IN" onChange={(e) => set({ country: e.target.value.toUpperCase().trim() })}/>
        </FormField>
      </FieldGroup>
      <FieldGroup cols={2}>
        <FormField label="Campaign type">
          <SegmentedControl value={f.pricing_model} onChange={(v) => set({ pricing_model: v })} options={[{ label: "CPC", value: "cpc" }, { label: "CPA", value: "cpa" }]}/>
        </FormField>
        <FormField label="Currency">
          <Select value={f.currency} onChange={(v) => set({ currency: v })} options={PW_CAMPAIGN_CURRENCIES.map((c) => ({ label: c, value: c }))}/>
        </FormField>
      </FieldGroup>
      <FieldGroup cols={3}>
        <FormField label={f.pricing_model === "cpa" ? "Min bid / conversion" : "Min bid / click"}><Input type="number" step="0.01" value={f.min_bid} onChange={(e) => set({ min_bid: e.target.value })}/></FormField>
        <FormField label="Min campaign budget"><Input type="number" step="0.01" value={f.min_campaign_budget} onChange={(e) => set({ min_campaign_budget: e.target.value })}/></FormField>
        <FormField label="Min top-up"><Input type="number" step="0.01" value={f.min_topup} onChange={(e) => set({ min_topup: e.target.value })}/></FormField>
      </FieldGroup>
      <FormField label="Effective from" hint="Blank: now. Never in the past — a back-dated minimum would restate campaigns already priced.">
        <Input type="datetime-local" value={f.effective_from} onChange={(e) => set({ effective_from: e.target.value })}/>
      </FormField>
      <FormField label="Note" hint="Why this number — recorded with the row and in the audit trail.">
        <Input value={f.note} maxLength={500} onChange={(e) => set({ note: e.target.value })}/>
      </FormField>
      {!dateOk && <div style={{ fontSize: 12.5, color: "var(--bad)" }}>Effective date is in the past.</div>}
      {!countryOk && <div style={{ fontSize: 12.5, color: "var(--bad)" }}>Country is two letters (ISO-3166), e.g. IN.</div>}
    </FormFrame>
  );
};

Object.assign(window, { OpSegmentsScreen, SegmentCreateScreen, OpMinimumsScreen, MinimumCreateScreen });
