/* Taking a payment and raising a payout — the two records this desk makes
   itself. Both are their own registered route rather than a dialog, because
   both are more than three fields and both move money.

   Commit model: STAGED on both. Nothing exists until Save; Cancel appears once
   the form is dirty; errors render on validation, never on first paint. The
   preview beside each form is the real evaluator over the real fixture — the
   balance line is balanceBreakdown() with the drafted amount taken out of it.

   Data state: populated (the customer list) plus the form's own idle state.
   Entitlements gate controls, not copy: a customer who cannot be paid out is
   not in the options, and the field says why. */
(() => {
  const {
    Card, CardHeader, CardTitle, CardDescription, CardPanel, CardFooter,
    Field, FieldLabel, FieldDescription, FieldError, Input, InputGroup, InputGroupAddon, InputGroupText, InputGroupInput,
    Select, RadioGroup, Button, Badge, Separator, Alert, AlertTitle, AlertDescription,
  } = window.OriginDesignSystem_7c998b;

  const centsOf = (text) => Math.round(Number(String(text).replace(/[^0-9.]/g, "")) * 100) || 0;

  /* ── New payment ──────────────────────────────────────────────────────── */

  function NewPaymentScreen({ data, now, onCreate, onNavigate }) {
    /* Only an account that is trading can be charged. Closed and suspended
       accounts are out of the options rather than in them and rejected. */
    const chargeable = data.customers.filter((c) => c.status === "live" || c.status === "on_hold");
    const blank = { customerId: chargeable.length ? chargeable[0].id : "", method: "card", amount: "", reference: "" };
    const [draft, setDraft] = React.useState(blank);
    const [submitted, setSubmitted] = React.useState(false);
    const set = (fields) => setDraft((d) => Object.assign({}, d, fields));
    const dirty = JSON.stringify(draft) !== JSON.stringify(blank);
    const cents = centsOf(draft.amount);
    const customer = data.customers.find((c) => c.id === draft.customerId) || null;
    const errors = {};
    if (!customer) errors.customerId = "Pick the account being charged.";
    if (cents < 100) errors.amount = "At least $1.00 — anything smaller costs more to process than it collects.";
    if (cents > 100000000) errors.amount = "Over $1,000,000 has to go through treasury as a wire.";
    const valid = Object.keys(errors).length === 0;
    const fee = cents ? methodFee(draft.method, cents) : 0;
    const theirs = customer ? paymentsFor(data.payments, customer) : [];

    return (
      <div className="fd-page">
        <PageHeader path="/payments/new" title="New payment" />
        <div className="fd-columns">
          <div className="fd-col">
            <Card>
              <CardHeader>
                <CardTitle>Charge a customer</CardTitle>
                <CardDescription>It is created as pending and settles on the method's own clock. Nothing is captured here.</CardDescription>
              </CardHeader>
              <CardPanel>
                <div className="fd-fields">
                  <Field>
                    <FieldLabel htmlFor="fd-pay-cus">Customer</FieldLabel>
                    <Select id="fd-pay-cus" value={draft.customerId} onValueChange={(id) => set({ customerId: id })}
                      items={chargeable.map((c) => ({ value: c.id, label: c.name + (c.status === "on_hold" ? " — on hold, money can still arrive" : "") }))} />
                    <FieldDescription>
                      {data.customers.length - chargeable.length} of {data.customers.length} accounts are left out: a suspended or closed account cannot be charged.
                    </FieldDescription>
                  </Field>
                  <Field>
                    <FieldLabel>How they are paying</FieldLabel>
                    <RadioGroup name="fd-pay-method" value={draft.method} onValueChange={(method) => set({ method: method })}
                      items={PAYMENT_METHODS.map((m) => ({ value: m.value, label: m.label }))} />
                    <FieldDescription>The method decides the fee and how long it takes to settle.</FieldDescription>
                  </Field>
                  <Field>
                    <FieldLabel htmlFor="fd-pay-amount">Amount</FieldLabel>
                    <InputGroup data-invalid={submitted && !!errors.amount ? "" : undefined}>
                      <InputGroupAddon><InputGroupText>$</InputGroupText></InputGroupAddon>
                      <InputGroupInput id="fd-pay-amount" inputMode="decimal" placeholder="1,250.00" value={draft.amount}
                        aria-invalid={(submitted && !!errors.amount) || undefined} onChange={(e) => set({ amount: e.target.value })} />
                    </InputGroup>
                    {submitted && errors.amount ? <FieldError>{errors.amount}</FieldError> : <FieldDescription>In {data.balance.currency}, the workspace's settlement currency.</FieldDescription>}
                  </Field>
                  <Field>
                    <FieldLabel htmlFor="fd-pay-ref">Reference</FieldLabel>
                    <Input id="fd-pay-ref" value={draft.reference} placeholder="Invoice 4417" onChange={(e) => set({ reference: e.target.value })} />
                    <FieldDescription>Optional. Shown to the customer beside {MERIDIAN_WORKSPACE.descriptor} on their statement.</FieldDescription>
                  </Field>
                </div>
              </CardPanel>
            </Card>
          </div>

          <div className="fd-col">
            <Card className="fd-card">
              <CardHeader>
                <CardTitle>What this collects</CardTitle>
                <CardDescription>Read from the form, priced off the fee schedule.</CardDescription>
              </CardHeader>
              <CardPanel className="fd-stack">
                <dl className="fd-defs">
                  <div><dt>Charged</dt><dd>{cents ? formatMoney(cents) : "—"}</dd></div>
                  <div><dt>Processing fee</dt><dd>{cents ? formatMoney(fee) + " · " + labelOf(PAYMENT_METHODS, draft.method).toLowerCase() : "—"}</dd></div>
                  <div><dt>Status on save</dt><dd><StatusBadge values={PAYMENT_STATUS} value="pending" /></dd></div>
                  <div className="fd-defs__total"><dt>Reaches the balance</dt><dd>{cents ? formatMoney(cents - fee) : "—"}</dd></div>
                </dl>
                {customer ? (
                  <>
                    <Separator />
                    <span className="fd-footnote">
                      {theirs.length
                        ? customer.name + " has been charged " + theirs.length + " times before, " + formatMoney(customerVolume(data.payments, customer)) + " of it succeeded."
                        : customer.name + " has never been charged."}
                      {CUSTOMER_FLAGS.hasOpenDispute(customer, data.disputes) ? " They have an open dispute — worth a word with the owner first." : ""}
                    </span>
                  </>
                ) : null}
              </CardPanel>
              <CardFooter className="fd-card-footer">
                {customer ? <Button variant="outline" size="sm" onClick={() => onNavigate(recordRoute({ type: "customer", id: customer.id }))}>Open {customer.name}<Icon name="arrow-right" /></Button> : null}
              </CardFooter>
            </Card>
          </div>
        </div>

        <FormBar
          dirty={dirty}
          note={dirty ? "Nothing is charged until this is saved." : "The customer, the method and the amount are all it takes."}
          onCancel={() => { setDraft(blank); setSubmitted(false); onNavigate("/payments"); }}
          onSave={() => { setSubmitted(true); if (valid) onCreate({ customer: customer.name, method: draft.method, amount: cents, reference: draft.reference.trim() }); }}
          label="New payment"
        />
      </div>
    );
  }

  /* ── New payout ───────────────────────────────────────────────────────── */

  function NewPayoutScreen({ data, now, onCreate, onNavigate }) {
    /* A payout needs a live account with a bank account on file. On hold,
       suspended and closed accounts, and anybody without bank details, are out
       of the options — and the field says how many and why. */
    const payable = data.customers.filter((c) => c.status === "live" && !!c.payoutAccount);
    const blank = { customerId: payable.length ? payable[0].id : "", amount: "", reference: "" };
    const [draft, setDraft] = React.useState(blank);
    const [submitted, setSubmitted] = React.useState(false);
    const set = (fields) => setDraft((d) => Object.assign({}, d, fields));
    const dirty = JSON.stringify(draft) !== JSON.stringify(blank);
    const cents = centsOf(draft.amount);
    const customer = data.customers.find((c) => c.id === draft.customerId) || null;
    const balance = balanceBreakdown(data.balance, data.payouts, data.disputes);
    const errors = {};
    if (!customer) errors.customerId = "Pick the account being paid.";
    if (cents < 100) errors.amount = "At least $1.00.";
    else if (cents > balance.available) errors.amount = "Only " + formatMoney(balance.available) + " is available today — " + formatMoney(balance.committed) + " is already committed to payouts in flight.";
    const valid = Object.keys(errors).length === 0;
    const limit = (data.members.find((m) => m.id === MERIDIAN_SIGNED_IN) || {}).approvalLimit || 0;

    return (
      <div className="fd-page">
        <PageHeader path="/payouts/new" title="New payout" />

        {payable.length === 0 ? (
          <Alert variant="warning">
            <AlertTitle>No account can be paid out today</AlertTitle>
            <AlertDescription>A payout needs a live account with bank details on file. Add them on the customer's own page first.</AlertDescription>
          </Alert>
        ) : null}

        <div className="fd-columns">
          <div className="fd-col">
            <Card>
              <CardHeader>
                <CardTitle>Send money to a customer</CardTitle>
                <CardDescription>It is raised awaiting approval, exactly like a payout the platform raises for itself — nobody can approve their own.</CardDescription>
              </CardHeader>
              <CardPanel>
                <div className="fd-fields">
                  <Field>
                    <FieldLabel htmlFor="fd-po-cus">Destination</FieldLabel>
                    <Select id="fd-po-cus" value={draft.customerId} onValueChange={(id) => set({ customerId: id })}
                      items={payable.map((c) => ({ value: c.id, label: c.name + " · " + c.payoutAccount }))} />
                    <FieldDescription>
                      {data.customers.length - payable.length} of {data.customers.length} accounts cannot be paid: no bank details, on hold, suspended or closed.
                    </FieldDescription>
                  </Field>
                  <Field>
                    <FieldLabel htmlFor="fd-po-amount">Amount</FieldLabel>
                    <InputGroup data-invalid={submitted && !!errors.amount ? "" : undefined}>
                      <InputGroupAddon><InputGroupText>$</InputGroupText></InputGroupAddon>
                      <InputGroupInput id="fd-po-amount" inputMode="decimal" placeholder="12,500.00" value={draft.amount}
                        aria-invalid={(submitted && !!errors.amount) || undefined} onChange={(e) => set({ amount: e.target.value })} />
                    </InputGroup>
                    {submitted && errors.amount ? <FieldError>{errors.amount}</FieldError> : <FieldDescription>{formatMoney(balance.available)} is available today.</FieldDescription>}
                  </Field>
                  <Field>
                    <FieldLabel htmlFor="fd-po-ref">Why</FieldLabel>
                    <Input id="fd-po-ref" value={draft.reference} placeholder="Weekly settlement, week to Wednesday" onChange={(e) => set({ reference: e.target.value })} />
                    <FieldDescription>Optional, and read by whoever approves it.</FieldDescription>
                  </Field>
                </div>
              </CardPanel>
            </Card>
          </div>

          <div className="fd-col">
            <Card className="fd-card">
              <CardHeader>
                <CardTitle>What this commits</CardTitle>
                <CardDescription>The balance chain with the drafted amount taken out of it.</CardDescription>
              </CardHeader>
              <CardPanel className="fd-stack">
                <dl className="fd-defs">
                  <div><dt>Available today</dt><dd>{formatMoney(balance.available)}</dd></div>
                  <div><dt>This payout</dt><dd>{cents ? "− " + formatMoney(cents) : "—"}</dd></div>
                  <div><dt>Already committed</dt><dd>{formatMoney(balance.committed)} to {pendingPayouts(data.payouts).length} payouts in flight</dd></div>
                  <div className="fd-defs__total"><dt>Available if approved</dt><dd>{formatMoney(Math.max(0, balance.available - cents))}</dd></div>
                </dl>
                <Separator />
                <span className="fd-footnote">
                  Raised as <strong>awaiting approval</strong>. {limit ? "Your own limit is " + formatMoney(limit) + ", and this one " + (cents && cents > limit ? "is above it, so somebody else has to sign it off." : "sits inside it.") : "You cannot approve payouts yourself, so it goes to whoever can."}
                </span>
              </CardPanel>
              <CardFooter className="fd-card-footer">
                <Button variant="outline" size="sm" onClick={() => onNavigate("/balances")}>Where the balance sits<Icon name="arrow-right" /></Button>
              </CardFooter>
            </Card>
          </div>
        </div>

        <FormBar
          dirty={dirty}
          note={dirty ? "Nothing leaves the balance until this is approved on the queue." : "Pick an account and an amount; approval is a separate step."}
          onCancel={() => { setDraft(blank); setSubmitted(false); onNavigate("/payouts"); }}
          onSave={() => { setSubmitted(true); if (valid) onCreate({ destination: customer.name, account: customer.payoutAccount, amount: cents, reference: draft.reference.trim() }); }}
          label="New payout"
        />
      </div>
    );
  }

  Object.assign(window, { NewPaymentScreen, NewPayoutScreen });
})();
