/* Money — what the brands owe us on the left, what we owe the creators on the
   right, and the commission that is the difference between them.
   Commit model: INSTANT. Issuing, chasing and recording a payment apply
   immediately and raise an undo toast. Releasing a payout is money leaving the
   account and cannot be recalled, so it opens a confirm dialog. No Save button.
   Data state: populated. Every deal carries an invoice and a payout from the
   moment it is agreed, so neither ledger is ever empty while a deal exists.
   Scope: every deal, all time. No period control, so no figure moves under you.
   Recession: a payout waiting on a brand is recessed and names the brand that
   is holding it — that is the whole point of putting the two ledgers side by
   side. A paid row is not recessed: finished is not blocked.
   Primary display: two facing ledgers rather than two tables, because the fact
   that matters is which side is blocking the other, and a join would hide it. */
(() => {
  const { Button, MenuItem, Alert, AlertTitle, AlertDescription, AlertAction } = window.OriginDesignSystem_7c998b;

  function MoneyRow({ title, meta, note, amount, status, clock, transitions, recessed, onTransition, onNavigate, dealId }) {
    const primary = transitions.find((t) => t.primary);
    const rest = transitions.filter((t) => !t.primary);
    return (
      <div className={"mq-row" + (recessed ? " mq-row--recessed" : "")}>
        <div className="mq-row__main" style={{ gridColumn: "1 / 3" }}>
          <span className="mq-row__title">
            <button type="button" className="mq-link" onClick={() => onNavigate("/deals/" + dealId)}>{title}</button>
          </span>
          <span className="mq-row__meta">{meta}</span>
          {note ? <span className="mq-row__meta">{note}</span> : null}
        </div>
        <div className="mq-row__side">
          <span className="mq-cellstack mq-cellstack--end">
            <span className="mq-amount">{amount}</span>
            {clock}
          </span>
          {status}
          {transitions.length === 0 ? null : recessed ? (
            <Floating align="end" width="14rem" label="Actions"
              trigger={<Button variant="ghost" size="icon-xs" aria-label={"Actions for " + title}><Icon name="ellipsis" size={14} /></Button>}>
              {(close) => transitions.map((t) => <MenuItem key={t.id} onClick={() => { close(); onTransition(t); }}>{t.label}</MenuItem>)}
            </Floating>
          ) : (
            <>
              {primary ? <Button size="xs" variant={primary.kind === "confirm" ? "default" : "outline"} onClick={() => onTransition(primary)}>{primary.label}</Button> : null}
              {rest.length ? (
                <Floating align="end" width="14rem" label="More actions"
                  trigger={<Button variant="ghost" size="icon-xs" aria-label={"More actions for " + title}><Icon name="ellipsis" size={14} /></Button>}>
                  {(close) => rest.map((t) => <MenuItem key={t.id} onClick={() => { close(); onTransition(t); }}>{t.label}</MenuItem>)}
                </Floating>
              ) : null}
            </>
          )}
        </div>
      </div>
    );
  }

  function MoneyScreen({ data, now, onNavigate, onInvoiceTransition, onPayoutTransition, pushToast }) {
    const invoices = invoiceRows(data.deals);
    const payouts = payoutRows(data.deals, data.creators);
    const awaitingBrand = invoicesAwaitingBrand(invoices);
    const overdue = invoicesOverdue(invoices, now);
    const toIssue = invoicesToIssue(invoices);
    const owed = payoutsOwed(payouts);
    const releasable = payoutsReleasable(payouts);
    const blocked = payoutsBlocked(payouts);
    /* Of the blocked payouts, the ones a past-due invoice is actually holding —
       the rest are waiting on an invoice that is not late, or not yet issued. */
    const blockedByOverdue = blocked.filter((r) => INVOICE_FLAGS.isOverdue(r.deal.invoice, now));
    const banked = commissionBanked(invoices);
    const pending = commissionPending(invoices);
    const run = nextPayoutRun(now);

    const orderInvoices = invoices.slice().sort((a, b) => {
      const rank = (r) => (INVOICE_FLAGS.isOverdue(r.invoice, now) ? 0 : r.invoice.status === "issued" ? 1 : r.invoice.status === "draft" ? 2 : 3);
      return rank(a) - rank(b) || (b.invoice.issuedAt || 0) - (a.invoice.issuedAt || 0);
    });
    const orderPayouts = payouts.slice().sort((a, b) => {
      const rank = (r) => (r.payout.status === "due" ? 0 : r.payout.status === "awaiting_funds" ? 1 : 2);
      return rank(a) - rank(b) || b.amount - a.amount;
    });

    return (
      <div className="mq-page">
        <PageHead
          path="/money"
          title="Money"
          lede={overdue.length
            ? formatMoney(moneyTotal(overdue)) + " is past due from " + overdue.map((r) => r.deal.brand).join(", ") + ", and it is the reason " + blockedByOverdue.map((r) => r.creator.name.split(" ")[0] + "'s " + formatMoney(r.amount)).join(" and ") + " cannot move. " + releasable.length + " payout" + (releasable.length === 1 ? " is" : "s are") + " funded and ready for the run on " + formatAbsolute(run).split(",")[0] + "."
            : "Nothing is past due. " + formatMoney(moneyTotal(awaitingBrand)) + " is with brands and " + formatMoney(moneyTotal(owed)) + " is owed to creators."}
          actions={<ExportMenu scope="Invoices and payouts" onExport={(format) => pushToast({ title: "Export started", description: "Money · " + format + " — we'll email it to " + MARQUE_FINANCE.name.split(" ")[0].toLowerCase() + "@marque.example" })} />}
        />

        {overdue.length ? (
          <Alert variant="error">
            <AlertTitle>{overdue.length === 1 ? overdue[0].deal.brand + " is " + INVOICE_FLAGS.daysOverdue(overdue[0].invoice, now) + " days past due" : overdue.length + " invoices are past due"}</AlertTitle>
            <AlertDescription>
              {overdue.map((r) => {
                const payout = payouts.find((p) => p.deal.id === r.deal.id);
                return (
                  <span key={r.deal.id}>
                    {formatMoney(r.amount)} on {r.invoice.id}, due {formatAbsolute(INVOICE_FLAGS.dueAt(r.invoice)).split(",")[0]}
                    {r.invoice.chasedAt ? ", chased " + formatAbsolute(r.invoice.chasedAt).split(",")[0] : ", not chased yet"}.
                    {" "}{payout.creator.name} is owed {formatMoney(payout.amount)} behind it.{" "}
                  </span>
                );
              })}
            </AlertDescription>
          </Alert>
        ) : null}

        <div className="mq-bleed">
          <div className="mq-figures">
            <Figure size="xl" label="Owed by brands" value={formatMoney(moneyTotal(awaitingBrand))} note={awaitingBrand.length + (awaitingBrand.length === 1 ? " invoice issued and unpaid, of which " : " invoices issued and unpaid, of which ") + formatMoney(moneyTotal(overdue)) + " is past due"} />
            <Figure size="xl" label="Owed to creators" value={formatMoney(moneyTotal(owed))} note={releasable.length + " funded and ready, " + formatMoney(moneyTotal(blocked)) + " held behind a brand"} />
            <Figure size="xl" label="Commission banked" value={formatMoney(banked)} note={formatMoney(pending) + " more sits on invoices nobody has paid yet"} />
            {toIssue.length ? (
              <Figure size="xl" label="Not yet invoiced" value={formatMoney(moneyTotal(toIssue))} note={toIssue.map((r) => r.deal.brand + " — " + r.invoice.holdReason.toLowerCase()).join(" · ")} />
            ) : null}
          </div>
        </div>

        <div className="mq-facing">
          <section className="mq-section">
            <div className="mq-ledgerhead">
              <div className="mq-col mq-col--tight">
                <Eyebrow>In</Eyebrow>
                <h2 className="mq-h2">What the brands owe us</h2>
              </div>
              <span className="mq-note">{invoices.length} invoices · overdue first</span>
            </div>
            <div className="mq-rows">
              {orderInvoices.map((row) => {
                const isOverdue = INVOICE_FLAGS.isOverdue(row.invoice, now);
                return (
                  <MoneyRow
                    key={row.invoice.id}
                    dealId={row.deal.id}
                    title={row.deal.brand}
                    meta={row.invoice.id + " · " + row.deal.title + " · " + creatorById(data.creators, row.deal.creatorId).name}
                    note={row.invoice.status === "draft"
                      ? row.invoice.holdReason
                      : row.invoice.status === "paid"
                        ? "Paid " + formatAbsolute(row.invoice.paidAt).split(",")[0] + " · commission " + formatMoney(commissionOf(row.deal)) + " banked"
                        : "Issued " + formatAbsolute(row.invoice.issuedAt).split(",")[0] + ", net " + AGENCY_POLICY.paymentTermsDays + (row.invoice.chasedAt ? " · chased " + formatAbsolute(row.invoice.chasedAt).split(",")[0] : "")}
                    amount={formatMoney(row.amount)}
                    status={<StatusBadge values={INVOICE_STATUS} value={row.invoice.status} />}
                    clock={row.invoice.status === "issued"
                      ? <span className={"mq-mono " + (isOverdue ? "mq-bad" : "mq-muted")} title={formatAbsolute(INVOICE_FLAGS.dueAt(row.invoice))}>{formatCountdown(INVOICE_FLAGS.dueAt(row.invoice), now)}</span>
                      : null}
                    transitions={invoiceTransitions(row.invoice)}
                    onTransition={(t) => onInvoiceTransition(row, t)}
                    onNavigate={onNavigate}
                  />
                );
              })}
            </div>
            <div className="mq-foot">
              <span>{formatMoney(moneyTotal(awaitingBrand))} issued and unpaid · {formatMoney(moneyTotal(toIssue))} not yet issued · {formatMoney(moneyTotal(invoicesPaid(invoices)))} banked</span>
            </div>
          </section>

          <div className="mq-spine" aria-hidden="true" />

          <section className="mq-section">
            <div className="mq-ledgerhead">
              <div className="mq-col mq-col--tight">
                <Eyebrow>Out</Eyebrow>
                <h2 className="mq-h2">What we owe the creators</h2>
              </div>
              <span className="mq-note">Net of commission · ready first</span>
            </div>
            <div className="mq-rows">
              {orderPayouts.map((row) => (
                <MoneyRow
                  key={row.payout.id}
                  dealId={row.deal.id}
                  title={row.creator.name}
                  meta={row.payout.id + " · " + row.deal.brand + " · " + formatMoney(row.deal.feeCents) + " less " + Math.round(row.deal.commissionRate * 100) + "%"}
                  note={row.payout.status === "awaiting_funds"
                    ? "Held until " + row.deal.brand + " pay " + row.deal.invoice.id + (INVOICE_FLAGS.isOverdue(row.deal.invoice, now) ? " — " + INVOICE_FLAGS.daysOverdue(row.deal.invoice, now) + " days past due" : row.deal.invoice.status === "draft" ? " — not issued yet" : "")
                    : row.payout.status === "paid"
                      ? "Released " + formatAbsolute(row.payout.paidAt).split(",")[0] + " · " + row.payout.reference
                      : row.deal.brand + " paid " + formatAbsolute(row.deal.invoice.paidAt).split(",")[0] + ". Next run is " + formatAbsolute(run).split(",")[0] + "."}
                  amount={formatMoney(row.amount)}
                  status={<StatusBadge values={PAYOUT_STATUS} value={row.payout.status} />}
                  transitions={payoutTransitions(row.payout)}
                  recessed={PAYOUT_FLAGS.isBlocked(row.payout)}
                  onTransition={(t) => onPayoutTransition(row, t)}
                  onNavigate={onNavigate}
                />
              ))}
            </div>
            <div className="mq-foot">
              <span>{formatMoney(moneyTotal(releasable))} ready to release · {formatMoney(moneyTotal(blocked))} held behind a brand · {formatMoney(moneyTotal(payouts.filter((r) => PAYOUT_FLAGS.isSettled(r.payout))))} paid</span>
            </div>
          </section>
        </div>
      </div>
    );
  }

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