// =================================================================
// pw-screens-payout-setup.jsx — Payout setup (payments phase 8, migration 0062)
//
//   Publisher: the registered address, and onboarding on the gateway its country picks —
//   India -> PayU Payouts (a bank account verified by penny drop), everywhere else -> Stripe
//   Connect Express (Stripe-hosted onboarding). Payouts stay blocked until the address is complete,
//   onboarding is complete and verification is approved.
//
//   Operator: onboarding status per publisher, paged and scoped like every other operator list.
//
//   Bank account numbers are sent once, to the API, which forwards them to PayU. Nothing on this page
//   ever shows one back — only the last four digits.
// =================================================================

const PO_STATUS_TONE = { not_started: "neutral", pending: "warn", in_review: "info", action_required: "bad", complete: "good", failed: "bad" };
const PO_BLOCKER_LABEL = { address_required: "Address required", onboarding_incomplete: "Onboarding incomplete", not_verified: "Not verified" };
const poGatewayLabel = (g) => (g === "payu" ? "PayU (India)" : g === "stripe" ? "Stripe" : "—");
const poStatus = (s) => String(s || "not_started").replace(/_/g, " ");

// A native select: 249 countries need the browser's type-to-find.
const CountrySelect = ({ value, onChange, disabled }) => (
  <select value={value || ""} disabled={disabled} onChange={(e) => onChange(e.target.value)}
    style={{ width: "100%", height: "var(--row)", border: "1px solid var(--line)", borderRadius: 8, background: "var(--panel)", color: "var(--ink)", padding: "0 10px", font: "inherit" }}>
    <option value="">Country</option>
    {window.pwCountryOptions().map((o) => <option key={o.value} value={o.value}>{o.label}</option>)}
  </select>
);

/** Structured address fields. `value` is { line1, line2, city, region, postal_code, country }. */
const AddressFields = ({ value, onChange, countryLocked, readOnly }) => {
  const set = (k) => (e) => onChange({ ...value, [k]: e && e.target ? e.target.value : e });
  return (
    <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }}>
      <div style={{ gridColumn: "1 / -1" }}><Input value={value.line1 || ""} onChange={set("line1")} placeholder="Address line 1" maxLength={200} disabled={readOnly}/></div>
      <div style={{ gridColumn: "1 / -1" }}><Input value={value.line2 || ""} onChange={set("line2")} placeholder="Address line 2 (optional)" maxLength={200} disabled={readOnly}/></div>
      <Input value={value.city || ""} onChange={set("city")} placeholder="City" maxLength={100} disabled={readOnly}/>
      <Input value={value.region || ""} onChange={set("region")} placeholder="State or region" maxLength={100} disabled={readOnly}/>
      <Input value={value.postal_code || ""} onChange={set("postal_code")} placeholder="Postcode" maxLength={20} disabled={readOnly}/>
      <CountrySelect value={value.country} onChange={set("country")} disabled={countryLocked || readOnly}/>
    </div>
  );
};

const emptyAddress = () => ({ line1: "", line2: "", city: "", region: "", postal_code: "", country: "" });
const addressFrom = (a) => ({ ...emptyAddress(), ...Object.fromEntries(Object.entries(a || {}).map(([k, v]) => [k, v == null ? "" : String(v)])) });

// ---------- Publisher: Payout setup ----------
const PayoutSetupScreen = ({ data, setData }) => {
  const live = Boolean(window.__api.getConfig().live);
  const [resp, setResp] = React.useState(live ? null : data.payoutOnboarding);
  const [loading, setLoading] = React.useState(live);
  const [addr, setAddr] = React.useState(emptyAddress());
  const [bank, setBank] = React.useState({ account_holder_name: "", account_number: "", ifsc: "" });
  const [busy, setBusy] = React.useState(false);
  const notify = (m, t) => window.__toast && window.__toast(m, t);

  const load = React.useCallback(async () => {
    if (!live) { setResp(data.payoutOnboarding); return; }
    setLoading(true);
    try { setResp(await window.__api.call("getPayoutOnboarding")); }
    catch (e) { notify("Could not load payout setup.", "bad"); }
    finally { setLoading(false); }
  }, [live, data.payoutOnboarding]);
  React.useEffect(() => { load(); }, [load]);

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

  if (loading || !ob) {
    return <Screen><PageHead icon={IconCard} title="Payout setup"/><Card><div style={{ padding: 24, textAlign: "center", color: "var(--muted)" }}>Loading…</div></Card></Screen>;
  }

  const missing = window.pwMissingAddressFields(addr);
  const nextGateway = addr.country ? (addr.country === "IN" ? "payu" : "stripe") : null;

  const saveAddress = async () => {
    setBusy(true);
    try {
      const registered_address = window.buildRegisteredAddress(addr);
      const res = await window.__api.write("savePayoutAddress", (d) => ({
        ...d,
        payoutOnboarding: d.payoutOnboarding && {
          ...d.payoutOnboarding,
          onboarding: {
            ...d.payoutOnboarding.onboarding, registered_address: { line2: null, ...registered_address },
            country: registered_address.country, gateway: registered_address.country === "IN" ? "payu" : "stripe",
            address_complete: true, address_missing: [],
            blockers: d.payoutOnboarding.onboarding.blockers.filter((b) => b !== "address_required"),
          },
        },
      }), { body: { registered_address }, ok: "Address saved", err: "Couldn’t save the address" });
      if (live) setResp(res);
    } catch (_) { /* toasted */ } finally { setBusy(false); }
  };

  const start = async () => {
    setBusy(true);
    try {
      if (!live) { notify("Demo mode: no payout provider is called.", "info"); return; }
      const res = await window.__api.call("startPayoutOnboarding", {});
      setResp({ ...resp, onboarding: res.onboarding });
      if (res.next && res.next.kind === "redirect") window.location.assign(res.next.url);
    } catch (e) {
      notify(e.message || "Couldn’t start onboarding.", "bad");
    } finally { setBusy(false); }
  };

  const submitBank = async () => {
    setBusy(true);
    try {
      const body = { account_holder_name: bank.account_holder_name.trim(), account_number: bank.account_number.replace(/\s+/g, ""), ifsc: bank.ifsc.trim().toUpperCase() };
      const res = await window.__api.write("submitPayoutBankAccount", null, { body, err: "Couldn’t verify the bank account" });
      // The number is cleared whatever happened: it is never kept in the page longer than the call.
      setBank({ account_holder_name: body.account_holder_name, account_number: "", ifsc: body.ifsc });
      if (live) {
        setResp({ ...resp, onboarding: res.onboarding });
        notify(res.outcome === "verified" ? "Bank account verified." : "The bank could not verify this account.", res.outcome === "verified" ? "good" : "warn");
      } else {
        notify("Demo mode: nothing was sent to PayU.", "info");
      }
    } catch (_) {
      setBank((b) => ({ ...b, account_number: "" }));
    } finally { setBusy(false); }
  };

  const acct = ob.onboarding;
  const req = (acct && acct.requirements) || { currently_due: [], past_due: [], eventually_due: [], disabled_reason: null };
  const bankOk = bank.account_holder_name.trim() && /^[0-9]{6,18}$/.test(bank.account_number.replace(/\s+/g, "")) && /^[A-Z]{4}0[A-Z0-9]{6}$/.test(bank.ifsc.trim().toUpperCase());

  return (
    <Screen>
      <PageHead icon={IconCard} title="Payout setup"
        subtitle="Where DropCap pays you. Your registered country decides the payout provider: India is paid through PayU, everywhere else through Stripe."/>

      {ob.eligible
        ? <Banner tone="info">Ready for payouts. Your details are held by {poGatewayLabel(ob.gateway)}; DropCap never stores your account number.</Banner>
        : <Banner tone="warn">Payouts are on hold until: {ob.blockers.map((b) => PO_BLOCKER_LABEL[b] || b).join(" · ")}.</Banner>}
      {resp.gateway_config_missing && resp.gateway_config_missing.length > 0 && (
        <Banner tone="info">{poGatewayLabel(ob.gateway)} payouts are not switched on yet. DropCap still needs: {resp.gateway_config_missing.join(", ")}.</Banner>
      )}

      <Card title="Registered address" subtitle={ob.country_locked
        ? "Your country is locked after your first payout. Contact support to change it."
        : "Your business's registered address. Changing the country restarts payout onboarding."}>
        <div style={{ display: "flex", flexDirection: "column", gap: 12, maxWidth: 620 }}>
          <AddressFields value={addr} onChange={setAddr} countryLocked={ob.country_locked}/>
          {!ob.address_complete && ob.country && <div style={{ fontSize: 12.5, color: "var(--warn)" }}>We have your country from verification. Please complete the rest of the address.</div>}
          {nextGateway && ob.country && nextGateway !== ob.gateway && <div style={{ fontSize: 12.5, color: "var(--warn)" }}>This moves your payouts to {poGatewayLabel(nextGateway)}; you will onboard again.</div>}
          <div><Btn kind="primary" disabled={busy || missing.length > 0} onClick={saveAddress}>{busy ? "Saving…" : "Save address"}</Btn></div>
        </div>
      </Card>

      <Card title={`Payout account · ${poGatewayLabel(ob.gateway)}`} subtitle="Held by the provider. DropCap keeps its reference and the last four digits only.">
        <div style={{ display: "flex", flexDirection: "column", gap: 12, maxWidth: 620 }}>
          <div style={{ display: "flex", gap: 10, alignItems: "center", flexWrap: "wrap", fontSize: 13 }}>
            <Pill tone={PO_STATUS_TONE[ob.onboarding_status] || "neutral"}>{poStatus(ob.onboarding_status)}</Pill>
            {acct && acct.bank_last4 && <span>Account ending {acct.bank_last4}</span>}
            {acct && acct.failure_reason && <span style={{ color: "var(--bad)" }}>{acct.failure_reason}</span>}
            <span style={{ color: "var(--muted)" }}>Verification: {poStatus(ob.verification_status)}</span>
          </div>

          {!ob.address_complete ? (
            <div style={{ fontSize: 13, color: "var(--muted)" }}>Complete your registered address first.</div>
          ) : ob.gateway === "stripe" ? (
            <>
              {(req.currently_due.length > 0 || req.past_due.length > 0) && (
                <div style={{ fontSize: 13, color: "var(--ink-2)" }}>
                  Stripe still needs: {[...req.past_due, ...req.currently_due].map((r) => r.replace(/[._]/g, " ")).join(", ")}.
                </div>
              )}
              {ob.onboarding_status !== "complete" && (
                <div><Btn kind="primary" disabled={busy} onClick={start}>
                  {busy ? "Opening Stripe…" : ob.onboarding_status === "not_started" ? "Set up payouts with Stripe" : "Continue on Stripe"}
                </Btn></div>
              )}
            </>
          ) : ob.onboarding_status !== "complete" ? (
            <>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }}>
                <div style={{ gridColumn: "1 / -1" }}>
                  <Input value={bank.account_holder_name} onChange={(e) => setBank({ ...bank, account_holder_name: e.target.value })} placeholder="Account holder name" maxLength={100}/>
                </div>
                <Input value={bank.account_number} type="password" autoComplete="off" inputMode="numeric"
                  onChange={(e) => setBank({ ...bank, account_number: e.target.value })} placeholder="Account number"/>
                <Input value={bank.ifsc} onChange={(e) => setBank({ ...bank, ifsc: e.target.value })} placeholder="IFSC" maxLength={11}/>
              </div>
              <div style={{ fontSize: 12.5, color: "var(--muted)" }}>PayU sends ₹1 to confirm the account and the holder's name.</div>
              <div><Btn kind="primary" disabled={busy || !bankOk} onClick={submitBank}>{busy ? "Verifying…" : "Verify bank account"}</Btn></div>
            </>
          ) : null}
        </div>
      </Card>
    </Screen>
  );
};

// ---------- Operator: onboarding status per publisher ----------
const OpPayoutOnboardingScreen = ({ data }) => {
  const list = useListQuery("adminListPayoutOnboarding", {
    sort: "publisher_name", dir: "asc", filters: { onboarding_status: "", gateway: "", eligible: "", address: "" }, watch: data.payoutOnboardingList,
  });
  React.useEffect(() => { if (list.error && window.__toast) window.__toast("Could not load payout onboarding.", "bad"); }, [list.error]);
  return (
    <Screen>
      <PageHead icon={IconCard} title="Payout onboarding"
        subtitle="Each publisher's registered country, payout provider and onboarding. A publisher is paid only when all three are done: address, onboarding, verification."/>
      <Banner tone="info">
        India is paid through PayU, everywhere else through Stripe. A country is locked after the first payout; only a superadmin can change it, and the change is audited.
      </Banner>
      <Card padded={false}>
        <div style={{ padding: "12px 16px", borderBottom: "1px solid var(--line-2)" }}>
          <ListToolbar list={list} placeholder="Search publisher"
            filters={[
              { key: "onboarding_status", label: "Statuses", options: statusOptions(["not_started", "pending", "in_review", "action_required", "complete", "failed"]) },
              { key: "gateway", label: "Providers", options: [{ label: "Stripe", value: "stripe" }, { label: "PayU", value: "payu" }] },
              { key: "eligible", label: "Eligibility", options: [{ label: "Eligible", value: "true" }, { label: "Blocked", value: "false" }] },
              { key: "address", label: "Address", options: [{ label: "Required", value: "required" }, { label: "Complete", value: "complete" }] },
            ]}/>
        </div>
        <DataTable rows={list.rows} keyField="publisher_id" server={list.server} empty="No publishers match."
          columns={[
            { key: "publisher_name", label: "Publisher", sortable: true, render: (r) => (
              <a href={`#/op-publisher-address?id=${encodeURIComponent(r.publisher_id)}`} title="Registered address"
                onClick={(e) => { e.preventDefault(); window.__nav("op-publisher-address", r.publisher_id); }}>{r.publisher_name}</a>
            ) },
            { key: "country", label: "Country", render: (r) => r.country
              ? <span>{r.country}{r.country_locked ? <span style={{ color: "var(--muted)", fontSize: 11.5 }}> · locked</span> : null}</span>
              : <span style={{ color: "var(--muted)" }}>—</span> },
            { key: "gateway", label: "Provider", render: (r) => poGatewayLabel(r.gateway) },
            { key: "onboarding_status", label: "Onboarding", sortable: true, render: (r) => <Pill tone={PO_STATUS_TONE[r.onboarding_status] || "neutral"}>{poStatus(r.onboarding_status)}</Pill> },
            { key: "requirements_due", label: "Due", align: "right", render: (r) => r.requirements_due || "—" },
            { key: "verification_status", label: "Verification", render: (r) => poStatus(r.verification_status) },
            { key: "eligible", label: "Payouts", render: (r) => r.eligible
              ? <Pill tone="good">eligible</Pill>
              : <span style={{ fontSize: 12.5, color: "var(--muted)" }}>{r.blockers.map((b) => PO_BLOCKER_LABEL[b] || b).join(", ")}</span> },
            { key: "updated_at", label: "Updated", sortable: true, render: (r) => r.updated_at ? <span style={{ fontSize: 12.5 }}>{fmt.date(r.updated_at)}</span> : "—" },
          ]}/>
      </Card>
    </Screen>
  );
};

Object.assign(window, { CountrySelect, AddressFields, PayoutSetupScreen, OpPayoutOnboardingScreen, emptyAddress, addressFrom, PO_STATUS_TONE, poGatewayLabel, poStatus });
