/* Spend — what running the house costs, what is owed, and what is committed.
   Commit model: INSTANT. Paying, querying and closing a query apply immediately
   with an undo toast; raising a bill is a staged dialog from this screen.

   Every figure divides one array: monthlyRunningCost, billsOutstanding and
   spendByKind all read data.bills and data.contracts, so nothing here can
   disagree with the rows beneath it. */
(() => {
  const {
    Button, Badge, Alert, AlertTitle, AlertDescription, Tabs, TabsList, TabsTab,
    Table, TableHeader, TableBody, TableRow, TableHead, TableCell, TableFooter,
  } = window.OriginDesignSystem_7c998b;

  function SpendScreen({ data, now, viewer, onNavigate, onBillTransition, onNewBill, onExport }) {
    const [tab, setTab] = React.useState("open");
    const { sort, onSort } = useSort("due", "asc");

    const monthly = monthlyRunningCost(data);
    const open = billsOpen(data.bills);
    const overdue = billsOverdue(data.bills, now);
    const disputed = billsDisputed(data.bills);
    const above = billsAboveForecast(data.bills);
    const contracts = contractsActive(data.contracts);
    const ending = contractsEndingSoon(data.contracts, now);
    const byKind = spendByKind(data.bills);

    const base = tab === "open" ? open.concat(disputed) : tab === "paid" ? data.bills.filter((b) => b.status === "paid") : data.bills;
    const rows = sortRows(base, sort, {
      due: (b) => b.dueAt,
      amount: (b) => b.amountMinor,
      supplier: (b) => b.supplier,
    });

    return (
      <>
        <PageHead path="/spend" title="Bills"
          lede={"Running " + RESIDENCE.short + " costs about " + formatPounds(monthly.total) + " a month: " + formatPounds(monthly.bills) + " in bills and " + formatPounds(monthly.contracts) + " in service contracts."}
          actions={
            <>
              <ExportMenu scope={"All " + data.bills.length + " bills and " + contracts.length + " contracts"} onExport={(format) => onExport("Bills", "Bills and contracts", data.bills.length, format)} />
              <Button size="sm" onClick={onNewBill}><Icon name="plus" />New bill</Button>
            </>
          } />

        <Figures items={[
          { label: "Owed now", value: formatPounds(billsOutstanding(data.bills)), qualifier: open.length + " open bills and " + disputed.length + " queried · " + overdue.length + " past their date" },
          { label: "A month to run", value: formatPounds(monthly.total), qualifier: monthly.rows.length + " recurring bills plus " + contracts.length + " contracts" },
          { label: "Above forecast", value: above.length, qualifier: above.length ? formatPounds(above.reduce((n, b) => n + (b.amountMinor - b.forecastMinor), 0)) + " more than expected, across " + above.reduce((list, b) => (list.indexOf(b.kind) > -1 ? list : list.concat([b.kind])), []).map((k) => labelOf(BILL_KINDS, k).toLowerCase()).join(", ") : "every bill came in at or under its forecast" },
          { label: "Committed", value: formatPounds(monthlyCommitted(data.contracts)), unit: "a month", qualifier: ending.length ? ending.length + " contracts end within 60 days" : "nothing ending within 60 days" },
        ]} />

        {overdue.length || above.length ? (
          <Band>
            <Card tint>
              <Alert variant={overdue.length ? "warning" : "info"}>
                <AlertTitle>{overdue.length ? (overdue.length === 1 ? "One bill is past its due date" : overdue.length + " bills are past their due date") : "Bills above forecast"}</AlertTitle>
                <AlertDescription>
                  {overdue.length
                    ? overdue.map((b) => b.supplier + " — " + formatPoundsExact(b.amountMinor) + ", due " + formatWhen(b.dueAt, now) + " (" + formatCountdown(b.dueAt, now) + ")").join(" · ")
                    : above.map((b) => b.supplier + " — " + formatPoundsExact(b.amountMinor - b.forecastMinor) + " above forecast").join(" · ")}
                  {above.some((b) => b.kind === "water") ? " The water figure and the overnight flow are the same story." : ""}
                </AlertDescription>
              </Alert>
            </Card>
          </Band>
        ) : null}

        <div className="hh-cols hh-cols--wide">
          <div>
            <Card flush title="Bills" note="What has arrived, what is owed and what has been paid."
              actions={
                <Tabs value={tab} onValueChange={setTab}>
                  <TabsList>
                    <TabsTab value="open" size="sm">Open ({open.length + disputed.length})</TabsTab>
                    <TabsTab value="paid" size="sm">Paid ({data.bills.filter((b) => b.status === "paid").length})</TabsTab>
                    <TabsTab value="all" size="sm">All ({data.bills.length})</TabsTab>
                  </TabsList>
                </Tabs>
              }>
              <TableWrap>
                <Table>
                  <TableHeader>
                    <TableRow>
                      <TableHead><SortHead label="Supplier" sortKey="supplier" sort={sort} onSort={onSort} /></TableHead>
                      <TableHead>For</TableHead>
                      <TableHead>Status</TableHead>
                      <TableHead className="hh-num"><SortHead label="Amount" sortKey="amount" sort={sort} onSort={onSort} /></TableHead>
                      <TableHead className="hh-num">Against forecast</TableHead>
                      <TableHead><SortHead label="Due" sortKey="due" sort={sort} onSort={onSort} /></TableHead>
                      <TableHead>Action</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {rows.map((bill) => {
                      const gap = bill.forecastMinor != null ? bill.amountMinor - bill.forecastMinor : null;
                      return (
                        <TableRow key={bill.id}>
                          <TableCell>
                            <span className="hh-person__text">
                              <span className="hh-person__name">{bill.supplier}</span>
                              <span className="hh-person__meta">{labelOf(BILL_KINDS, bill.kind)}</span>
                            </span>
                          </TableCell>
                          <TableCell>{bill.period}</TableCell>
                          <TableCell>
                            <span className="hh-actions__row">
                              <StatusBadge values={BILL_STATUS} value={bill.status} />
                              {BILL_FLAGS.overdue(bill, now) ? <Badge size="sm" variant="warning">{formatCountdown(bill.dueAt, now)}</Badge> : null}
                            </span>
                          </TableCell>
                          <TableCell className="hh-num">{formatPoundsExact(bill.amountMinor)}</TableCell>
                          <TableCell className="hh-num">
                            {gap == null ? <span className="hh-muted">—</span>
                              : gap > 0 ? <span className="hh-warn">{formatPoundsExact(gap)} over</span>
                                : gap < 0 ? <span className="hh-good">{formatPoundsExact(Math.abs(gap))} under</span>
                                  : <span className="hh-muted">as forecast</span>}
                          </TableCell>
                          <TableCell><Clock at={bill.dueAt} now={now} problem={bill.status === "due"} /></TableCell>
                          <TableCell><RowActions transitions={billTransitions(bill, viewer)} onRun={(t) => onBillTransition(bill, t)} label={"Actions for the " + bill.supplier + " bill"} /></TableCell>
                        </TableRow>
                      );
                    })}
                  </TableBody>
                  <TableFooter>
                    <TableRow>
                      <TableCell colSpan={3}>{tab === "open" ? "Open and queried" : tab === "paid" ? "Paid" : "Every bill"}</TableCell>
                      <TableCell className="hh-num">{formatPoundsExact(rows.reduce((n, b) => n + b.amountMinor, 0))}</TableCell>
                      <TableCell colSpan={3} />
                    </TableRow>
                  </TableFooter>
                </Table>
              </TableWrap>
              <TableFoot shown={rows.length} total={data.bills.length} noun="bills" />
            </Card>
          </div>

          <div>
            <Card title="What a month costs" note="The last paid bill of each kind, annual costs spread, plus the contracts.">
              <Rows>
                {monthly.rows.map((row) => (
                  <Row key={row.kind} title={row.label} value={formatPounds(row.minor)}
                    note={row.kind === "insurance" ? "A year's premium spread over twelve" : row.kind === "water" ? "A quarter's bill spread over three" : "The last month billed"}>
                    <span style={{ width: "4.5rem" }}><Bar percent={(row.minor / Math.max(1, monthly.total)) * 100} label={row.label + " share"} /></span>
                  </Row>
                ))}
                <Row title="Service contracts" value={formatPounds(monthly.contracts)} note={contracts.map((c) => c.name.split(",")[0].toLowerCase()).join(", ")}>
                  <span style={{ width: "4.5rem" }}><Bar percent={(monthly.contracts / Math.max(1, monthly.total)) * 100} label="Contract share" /></span>
                </Row>
              </Rows>
              <div style={{ display: "flex", justifyContent: "space-between", marginTop: "var(--space-4)", paddingTop: "var(--space-3)", borderTop: "1px solid var(--border)" }}>
                <span className="hh-row__title">A month, all in</span>
                <span className="hh-row__value">{formatPounds(monthly.total)}</span>
              </div>
            </Card>

            <Card title={"Service contracts (" + contracts.length + ")"} note="What is committed, and when each one is up for renewal."
              actions={<Button variant="outline" size="sm" onClick={() => onNavigate("/providers")}>Providers</Button>}>
              <Rows>
                {contracts.map((contract) => (
                  <Row key={contract.id} title={contract.name}
                    note={providerName(data.providers, contract.providerId) + " · " + formatPounds(contract.monthlyMinor) + " a month · " + (contract.endsAt ? "runs to " + formatWhen(contract.endsAt, now) : "no end date")}
                    meta={contract.note}>
                    {ending.indexOf(contract) > -1 ? <Badge size="sm" variant="warning">{formatCountdown(contract.endsAt, now)}</Badge> : null}
                    <Button variant="ghost" size="sm" onClick={() => onNavigate("/providers/" + contract.providerId)}>Provider</Button>
                  </Row>
                ))}
              </Rows>
            </Card>

            <Card title="Where the money goes" note="Every bill on the record, grouped by what it is for.">
              <Rows>
                {byKind.map((row) => (
                  <Row key={row.kind} title={row.label} value={formatPounds(row.minor)}
                    note={row.rows.length + (row.rows.length === 1 ? " bill" : " bills") + " on the record"}>
                    <span style={{ width: "5rem" }}><Bar percent={(row.minor / Math.max(1, byKind[0].minor)) * 100} label={row.label + " share"} /></span>
                  </Row>
                ))}
              </Rows>
            </Card>
          </div>
        </div>
      </>
    );
  }

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