// =================================================================
// pw-screens-op-publisher-address.jsx — Operator · a publisher's registered address (0062)
//
// Opened from Payout onboarding (#/op-publisher-address?id=<publisher_id>). Reuses the 0062 API:
//   GET /admin/v1/publishers/:id/payout-onboarding       — the address, country and lock
//   PUT /admin/v1/publishers/:id/registered-address      — the change, audited in the same transaction
//
// Who may do what:
//   * superadmin — edits. After the first payout the country is locked; a superadmin may still change
//     it, but only with a reason, which the API writes to audit_log with locked_override.
//   * manager — read-only, and only for assigned publishers (#89). The API scopes the read and
//     refuses an unassigned publisher with 403; this page shows that as "not assigned".
// The role shown here only decides what the page offers; the API and the database enforce it.
// =================================================================

const opAddrIsManager = (session) => String((session && session.user && session.user.roleLabel) || "").toLowerCase() === "manager";

// Demo: build the same view the API returns from the fixtures, honouring the demo manager's scope.
const opAddrDemoView = (data, publisherId) => {
  const entry = (data.payoutOnboardingList || []).find((r) => r.publisher_id === publisherId);
  if (!entry) return null;
  const addr = (data.opPublisherAddresses || {})[publisherId] || null;
  return {
    publisher_name: entry.publisher_name,
    onboarding: {
      publisher_id: publisherId, registered_address: addr, address_complete: entry.address_complete,
      address_missing: addr ? window.pwMissingAddressFields(addressFrom(addr)) : ["line1", "city", "region", "postal_code", "country"],
      country: entry.country, country_locked: entry.country_locked, gateway: entry.gateway,
      onboarding_status: entry.onboarding_status, verification_status: entry.verification_status,
      eligible: entry.eligible, blockers: entry.blockers,
    },
  };
};

const OpPublisherAddressScreen = ({ data, publisherId }) => {
  const live = Boolean(window.__api.getConfig().live);
  const { session } = useSession();
  const manager = opAddrIsManager(session);
  const scope = session && session.user && Array.isArray(session.user.publisher_ids) ? session.user.publisher_ids : null;

  const [state, setState] = React.useState({ loading: true, error: null, view: null });
  const [addr, setAddr] = React.useState(emptyAddress());
  const [reason, setReason] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const idem = React.useRef({ body: null, key: null });

  const load = React.useCallback(async () => {
    if (!publisherId) { setState({ loading: false, error: "missing", view: null }); return; }
    if (!live) {
      if (manager && scope && !scope.includes(publisherId)) { setState({ loading: false, error: "forbidden", view: null }); return; }
      const v = opAddrDemoView(data, publisherId);
      setState({ loading: false, error: v ? null : "not_found", view: v });
      return;
    }
    setState((s) => ({ ...s, loading: true }));
    try {
      const res = await window.__api.call("adminGetPayoutOnboarding", { params: { publisher_id: publisherId } });
      const name = ((data.payoutOnboardingList || []).find((r) => r.publisher_id === publisherId) || {}).publisher_name;
      setState({ loading: false, error: null, view: { publisher_name: name || null, onboarding: res.onboarding } });
    } catch (e) {
      setState({ loading: false, error: e && e.status === 403 ? "forbidden" : e && e.status === 404 ? "not_found" : "failed", view: null });
    }
  }, [live, publisherId, manager, data.payoutOnboardingList, data.opPublisherAddresses]);
  React.useEffect(() => { load(); }, [load]);

  const ob = state.view && state.view.onboarding;
  React.useEffect(() => { if (ob) { setAddr(addressFrom(ob.registered_address)); setReason(""); } }, [ob && JSON.stringify(ob.registered_address)]);

  const back = <Btn kind="ghost" size="sm" onClick={() => window.__nav("op-payout-onboarding")}>Back to payout onboarding</Btn>;
  const title = (state.view && state.view.publisher_name) || "Registered address";

  if (state.loading) {
    return <Screen><PageHead icon={IconBuilding} title="Registered address" actions={back}/><Card><div style={{ padding: 24, textAlign: "center", color: "var(--muted)" }}>Loading…</div></Card></Screen>;
  }
  if (state.error || !ob) {
    const msg = state.error === "forbidden" ? "This publisher is not assigned to you."
      : state.error === "missing" ? "No publisher selected."
      : state.error === "not_found" ? "Publisher not found."
      : "Could not load this publisher's address.";
    return <Screen><PageHead icon={IconBuilding} title="Registered address" actions={back}/><Banner tone={state.error === "failed" ? "bad" : "warn"}>{msg}</Banner></Screen>;
  }

  const current = addressFrom(ob.registered_address);
  const next = window.buildRegisteredAddress(addr);
  const countryChanged = Boolean(ob.country) && next.country !== String(ob.country || "").toUpperCase();
  const needsReason = ob.country_locked && countryChanged;
  const missing = window.pwMissingAddressFields(addr);
  const dirty = JSON.stringify(window.buildRegisteredAddress(current)) !== JSON.stringify(next);
  const canSave = !manager && dirty && missing.length === 0 && (!needsReason || reason.trim().length > 0) && !busy;

  const save = async () => {
    if (!canSave) return;
    setBusy(true);
    const body = { registered_address: next, ...(reason.trim() ? { reason: reason.trim() } : {}) };
    // A retry of the same change reuses its Idempotency-Key, so a double click cannot write twice.
    const bodyJson = JSON.stringify(body);
    if (idem.current.body !== bodyJson) idem.current = { body: bodyJson, key: (crypto.randomUUID ? crypto.randomUUID() : String(Date.now()) + Math.random()) };
    try {
      const res = await window.__api.write("adminSetRegisteredAddress", (d) => ({
        ...d,
        opPublisherAddresses: { ...(d.opPublisherAddresses || {}), [publisherId]: { line2: null, ...next } },
        payoutOnboardingList: (d.payoutOnboardingList || []).map((r) => r.publisher_id === publisherId
          ? { ...r, country: next.country, address_complete: true, gateway: next.country === "IN" ? "payu" : "stripe", blockers: r.blockers.filter((b) => b !== "address_required") }
          : r),
      }), { params: { publisher_id: publisherId }, body, idempotencyKey: idem.current.key, ok: "Address saved", err: "Couldn’t save the address" });
      idem.current = { body: null, key: null };
      if (live && res && res.onboarding) setState((s) => ({ ...s, view: { ...s.view, onboarding: res.onboarding } }));
    } catch (_) { /* toasted by write() */ } finally { setBusy(false); }
  };

  return (
    <Screen>
      <PageHead icon={IconBuilding} title={title} subtitle="Registered address and country. The country picks the payout provider." actions={back}/>

      {manager ? <Banner tone="info">Read only. Only a superadmin can change a publisher's registered address.</Banner> : null}

      <Card title="Registered address">
        <div style={{ display: "flex", flexDirection: "column", gap: 12, maxWidth: 620 }}>
          <div style={{ display: "flex", gap: 10, alignItems: "center", flexWrap: "wrap", fontSize: 13 }}>
            {ob.country_locked
              ? <Pill tone="warn">Country locked</Pill>
              : <Pill tone="neutral">Country open</Pill>}
            {ob.country_locked ? <span style={{ color: "var(--ink-2)" }}>Locked after this publisher's first payout.</span> : null}
            <span style={{ color: "var(--muted)" }}>Provider: {poGatewayLabel(ob.gateway)}</span>
            {!ob.address_complete ? <Pill tone="bad">Address required</Pill> : null}
          </div>

          <AddressFields value={addr} onChange={setAddr} readOnly={manager} countryLocked={manager}/>

          {!manager && needsReason ? (
            <Input value={reason} onChange={(e) => setReason(e.target.value)} placeholder="Reason for changing a locked country" maxLength={500}/>
          ) : null}
          {!manager && countryChanged && next.country ? (
            <div style={{ fontSize: 12.5, color: "var(--warn)" }}>Moves payouts to {poGatewayLabel(next.country === "IN" ? "payu" : "stripe")}; the publisher onboards again.</div>
          ) : null}

          {!manager ? (
            <div style={{ display: "flex", gap: 8 }}>
              <Btn kind="primary" disabled={!canSave} onClick={save}>{busy ? "Saving…" : "Save address"}</Btn>
              <Btn kind="ghost" disabled={!dirty || busy} onClick={() => { setAddr(current); setReason(""); }}>Reset</Btn>
            </div>
          ) : null}
        </div>
      </Card>
    </Screen>
  );
};

Object.assign(window, { OpPublisherAddressScreen });
