/* Payouts — the money going out, approval queue first.
   Commit model: INSTANT. Approve applies and raises an undo toast; reject is
   irreversible and opens a confirm dialog.
   Data state: populated, with a no-results branch for the filters.
   The figures are current rather than period-scoped — a queue has no period —
   and each names the array beneath it. */
(() => {
  const {
    Card, CardHeader, CardTitle, CardDescription, CardPanel, CardFooter,
    Table, TableHeader, TableBody, TableRow, TableHead, TableCell,
    Tabs, TabsList, TabsTab, Checkbox, Button, Badge,
    Empty, EmptyHeader, EmptyMedia, EmptyTitle, EmptyDescription, EmptyContent,
  } = window.OriginDesignSystem_7c998b;

  function PayoutsScreen({ data, now, onNavigate, onPayoutTransition, onBulkApprove, pushToast }) {
    const [query, setQuery] = React.useState("");
    const [status, setStatus] = React.useState("all");
    const [tab, setTab] = React.useState("queue");
    const [selected, setSelected] = React.useState([]);

    const approver = data.approver;
    const approvable = approvablePayouts(data.payouts, approver);
    const awaiting = awaitingApprovalPayouts(data.payouts);
    const blocked = awaiting.filter(PAYOUT_FLAGS.isBlocked);
    /* Held and above-your-limit are different exclusions and the screen says so
       separately: one is another team's decision, the other is yours to escalate. */
    const overLimit = awaiting.filter((p) => !PAYOUT_FLAGS.isBlocked(p) && PAYOUT_FLAGS.isAboveLimit(p, approver));
    const higherApprovers = (payout) => data.members.filter((m) => m.approvalLimit >= payout.amount);
    const inTransit = data.payouts.filter((p) => p.status === "in_transit");
    const scoped = tab === "queue" ? awaiting : data.payouts;
    const filtered = scoped.filter((p) => {
      if (query && (p.id + " " + p.destination + " " + p.account).toLowerCase().indexOf(query.toLowerCase()) === -1) return false;
      if (status !== "all" && p.status !== status) return false;
      return true;
    });
    const dirty = query !== "" || status !== "all";
    const clear = () => { setQuery(""); setStatus("all"); };
    const selectable = filtered.filter((p) => PAYOUT_FLAGS.isApprovable(p, approver));
    const picked = data.payouts.filter((p) => selected.indexOf(p.id) > -1);
    const toggle = (id) => setSelected((l) => (l.indexOf(id) > -1 ? l.filter((x) => x !== id) : l.concat([id])));
    const allPicked = selectable.length > 0 && selectable.every((p) => selected.indexOf(p.id) > -1);

    return (
      <div className="fd-page">
        <PageHeader path="/payouts" title="Payouts" actions={<span className="fd-actions__row"><ExportMenu scope={"All " + data.payouts.length + " payouts"} onExport={(format) => pushToast({ title: "Export started", description: data.payouts.length + " payouts · " + format })} /><Button size="sm" onClick={() => onNavigate("/payouts/new")}><Icon name="plus" />New payout</Button></span>} />

        <div className="fd-metrics">
          <MetricTile icon="check-check" label="Ready to approve" value={formatMoney(sumBy(approvable, "amount"))} qualifier={approvable.length + " of the " + awaiting.length + " waiting on us are unheld and inside your " + formatMoney(approver.approvalLimit) + " limit"} />
          <MetricTile icon="pause" label="Held or above your limit" value={formatMoney(sumBy(blocked.concat(overLimit), "amount"))} qualifier={blocked.length || overLimit.length ? [blocked.length ? blocked.length + " blocked by " + blocked.map((p) => p.blockedBy.team).join(", ") : null, overLimit.length ? overLimit.length + " above your " + formatMoney(approver.approvalLimit) + " limit" : null].filter(Boolean).join(", ") : "Nothing is held"} />
          <MetricTile icon="send" label="In transit" value={formatMoney(inTransitTotal(data.payouts))} qualifier={inTransit.length + " with the network, none of it recallable"} />
          <MetricTile icon="arrow-up-right" label="Committed" value={formatMoney(pendingPayoutTotal(data.payouts))} qualifier={pendingPayouts(data.payouts).length + " payouts that have not landed yet"} />
        </div>

        <FilterBar
          query={query} onQuery={setQuery} placeholder="Search by payout, destination or account" dirty={dirty} onClear={clear}
          selects={[{ id: "status", label: "Status", value: status, onChange: setStatus, items: [{ value: "all", label: "Every status" }].concat(PAYOUT_STATUS.map((s) => ({ value: s.id, label: s.label }))) }]}
        />

        <BulkBar
          count={picked.length}
          note={formatMoney(sumBy(picked, "amount")) + " would leave the balance."}
          onClear={() => setSelected([])}
        >
          <Button size="sm" onClick={() => { onBulkApprove(picked); setSelected([]); }}>Approve {picked.length} payouts</Button>
        </BulkBar>

        <Card>
          <CardHeader>
            <CardTitle>{tab === "queue" ? "Waiting on us" : "Every payout"}</CardTitle>
            <CardDescription>Only payouts with nothing in the way and inside your own approval limit can be selected or approved; the rest keep their row, their badge and their reason.</CardDescription>
          </CardHeader>
          <div className="fd-card-tabs">
            <Tabs value={tab} onValueChange={(next) => { setTab(next); setSelected([]); }}>
              <TabsList variant="underline">
                <TabsTab value="queue">Approval queue<span className="fd-tab-count">{awaiting.length}</span></TabsTab>
                <TabsTab value="all">All<span className="fd-tab-count">{data.payouts.length}</span></TabsTab>
              </TabsList>
            </Tabs>
          </div>
          {filtered.length === 0 ? (
            <CardPanel>
              <Empty>
                <EmptyHeader>
                  <EmptyMedia variant="icon"><Icon name="check-check" size={18} /></EmptyMedia>
                  <EmptyTitle>{dirty ? "No payouts match those filters" : "Nothing is waiting on us"}</EmptyTitle>
                  <EmptyDescription>{dirty ? "Widen the filters and try again." : "Every payout has been approved, sent or closed."}</EmptyDescription>
                </EmptyHeader>
                <EmptyContent>{dirty ? <Button onClick={clear}>Clear filters</Button> : <Button variant="outline" onClick={() => setTab("all")}>Show every payout</Button>}</EmptyContent>
              </Empty>
            </CardPanel>
          ) : (
            <div className="fd-card-table">
              <Table variant="card">
                <TableHeader>
                  <TableRow>
                    <TableHead style={{ width: "2.5rem" }}>
                      <Checkbox checked={allPicked} indeterminate={!allPicked && selectable.some((p) => selected.indexOf(p.id) > -1)}
                        aria-label="Select every approvable payout shown" onCheckedChange={(checked) => setSelected(checked ? selectable.map((p) => p.id) : [])} />
                    </TableHead>
                    <TableHead>Destination</TableHead>
                    <TableHead>Status</TableHead>
                    <TableHead className="fd-num">Amount</TableHead>
                    <TableHead className="fd-num fd-drop-md">Expected</TableHead>
                    <TableHead className="fd-actions-head">Action</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {filtered.map((payout) => {
                    /* Recession is for a payout nobody here can act on: it is
                       with the network or already closed. A held payout is
                       waiting on a person, so it stays at full weight. */
                    const recessed = ["in_transit", "paid", "rejected"].indexOf(payout.status) > -1;
                    const transitions = payoutTransitions(payout, approver);
                    const above = PAYOUT_FLAGS.awaitsApproval(payout) && !PAYOUT_FLAGS.isBlocked(payout) && PAYOUT_FLAGS.isAboveLimit(payout, approver);
                    const higher = above ? higherApprovers(payout) : [];
                    return (
                      <TableRow key={payout.id} className={recessed ? "fd-row--recessed" : undefined}>
                        <TableCell>
                          <Checkbox disabled={!PAYOUT_FLAGS.isApprovable(payout, approver)} checked={selected.indexOf(payout.id) > -1}
                            aria-label={"Select " + payout.id} onCheckedChange={() => toggle(payout.id)} />
                        </TableCell>
                        <TableCell>
                          <span className="fd-record">
                            <span className="fd-record__name">{payout.destination}</span>
                            <span className="fd-record__meta"><code>{payout.id}</code> · {payout.account}</span>
                          </span>
                        </TableCell>
                        <TableCell>
                          <StatusBadge values={PAYOUT_STATUS} value={payout.status} />
                          {payout.blockedBy ? <span className="fd-sub fd-waiting">Held by {payout.blockedBy.team} — {payout.blockedBy.reason}</span> : null}
                          {above ? <span className="fd-sub fd-waiting">Above your {formatMoney(approver.approvalLimit)} limit — {higher.length ? higher.map((m) => m.name).join(" or ") + " can release it" : "nobody here can release it on their own"}</span> : null}
                          {payout.returnReason ? <span className="fd-sub">{payout.returnReason}</span> : null}
                          {payout.rejectReason ? <span className="fd-sub">{payout.rejectReason}</span> : null}
                        </TableCell>
                        <TableCell className="fd-num fd-amount">{formatMoney(payout.amount)}</TableCell>
                        <TableCell className="fd-num fd-muted fd-drop-md" title={payout.expectedAt ? formatAbsolute(payout.expectedAt) : undefined}>
                          {payout.status === "paid" ? "Paid " + formatWhen(payout.paidAt, now) : payout.expectedAt ? formatWhen(payout.expectedAt, now) : "—"}
                        </TableCell>
                        <TableCell className="fd-actions">
                          {transitions.length
                            ? <Transitions transitions={transitions} onRun={(t) => onPayoutTransition(payout, t)} />
                            : payout.blockedBy
                              ? <span className="fd-muted">Waiting on {payout.blockedBy.team}</span>
                              : <span className="fd-muted">—</span>}
                        </TableCell>
                      </TableRow>
                    );
                  })}
                </TableBody>
              </Table>
            </div>
          )}
          <CardFooter className="fd-card-footer">
            <span className="fd-footnote">Showing {filtered.length} of {tab === "queue" ? awaiting.length + " waiting on us" : data.payouts.length + " payouts"}.</span>
            <span className="fd-footnote">{formatMoney(sumBy(filtered, "amount"))} across the rows shown.</span>
          </CardFooter>
        </Card>
      </div>
    );
  }

  Object.assign(window, { PayoutsScreen });
})();
