/* Work queue — the desk's home screen.
   Commit model: INSTANT. No Save button; the text filter and the tabs are
   harmless and apply as typed, the two chase actions apply immediately and
   raise an undo toast, and nothing on this screen is irreversible.
   Data state: populated. Empty and no-results are the other two branches of
   one conditional below — never on screen beside these rows.
   Scope: everything open on this desk. There is no period filter, so no figure
   on this screen moves when the tabs or the text filter change. */
(() => {
  const {
    Button, Input, Badge, Tabs, TabsList, TabsTab,
    Table, TableHeader, TableBody, TableRow, TableHead, TableCell,
    Empty, EmptyHeader, EmptyMedia, EmptyTitle, EmptyDescription, EmptyContent,
  } = window.OriginDesignSystem_7c998b;

  /* Tabs narrow the list only. Each one runs its own predicate — never a slice
     — and the labels name the looser things they count, because "on my desk"
     is deliberately wider than "decidable". */
  const QUEUE_TABS = [
    { value: "mine", label: "On my desk", predicate: CLAIM_FLAGS.awaitsAdjuster },
    { value: "others", label: "Waiting on others", predicate: CLAIM_FLAGS.isWaitingOnOthers },
    { value: "closed", label: "Closed", predicate: (c) => !CLAIM_FLAGS.isOpen(c) },
    { value: "all", label: "All", predicate: () => true },
  ];

  const matches = (claim, query) => {
    const q = query.trim().toLowerCase();
    if (!q) return true;
    return [claim.id, claim.customer, claim.container, claim.bl, claim.commodity].join(" ").toLowerCase().indexOf(q) > -1;
  };

  /* The burn-down: one bar per open claim on a single time-bar axis, positioned
     by days left and sized by the amount claimed. The deadline is the right
     wall. Every bar drills through to its claim. */
  function BurnDownBand({ claims, now, onNavigate }) {
    const open = openClaims(claims);
    const inside90 = claimsInsideDays(claims, 90, now);
    const total = CLAIM_POLICY.timeBarDays;
    const maxClaimed = Math.max.apply(null, open.map((c) => c.claimedCents));
    const zoneLeft = (days) => ((total - days) / total) * 100;
    const urgent = byUrgency(open, now).slice(0, 3);

    return (
      <div className="cd-bleed">
        <div className="cd-split cd-split--band">
          <div className="cd-section">
            <div className="cd-section__head">
              <h2 className="cd-h2">Time bar burn-down</h2>
            </div>
            <div className="cd-figures">
              <Figure xl label="Claimed and open" value={formatMoney(claimedExposure(open))} note={open.length + " claims still open, from " + claims.length + " on the desk"} />
              <Figure label="Inside 90 days" value={formatMoney(claimedExposure(inside90))} note={inside90.length + " of the " + open.length + " open claims, including anything already past the bar"} />
            </div>
            <div className="cd-burn">
              <span className="cd-burn__zone cd-burn__zone--warning" style={{ left: zoneLeft(TIME_TONE_DAYS.warning) + "%", width: (zoneLeft(TIME_TONE_DAYS.danger) - zoneLeft(TIME_TONE_DAYS.warning)) + "%" }} />
              <span className="cd-burn__zone cd-burn__zone--danger" style={{ left: zoneLeft(TIME_TONE_DAYS.danger) + "%", width: (100 - zoneLeft(TIME_TONE_DAYS.danger)) + "%" }} />
              {open.map((claim) => {
                const daysLeft = CLAIM_FLAGS.daysLeft(claim, now);
                const tone = timeTone(daysLeft);
                const x = Math.min(99, Math.max(1, ((total - daysLeft) / total) * 100));
                const height = 24 + 108 * Math.sqrt(claim.claimedCents / maxClaimed);
                return (
                  <FloatingTip key={claim.id} side="bottom" label={claim.customer + " · " + claim.id + " · " + formatMoney(claim.claimedCents) + " · " + formatCountdown(CLAIM_FLAGS.timeBarAt(claim), now)}>
                    <button
                      type="button"
                      className={"cd-burn__bar" + (tone === "neutral" ? "" : " cd-burn__bar--" + tone)}
                      style={{ left: x + "%", height: height + "px" }}
                      aria-label={claim.customer + ", " + formatMoney(claim.claimedCents) + " claimed, " + formatCountdown(CLAIM_FLAGS.timeBarAt(claim), now)}
                      onClick={() => onNavigate("/claims/" + claim.id)}
                    />
                  </FloatingTip>
                );
              })}
            </div>
            <div className="cd-burn__axis" aria-hidden="true">
              <span className="cd-burn__tick cd-burn__tick--first" style={{ left: "0%" }}>365 days left</span>
              <span className="cd-burn__tick" style={{ left: zoneLeft(180) + "%" }}>180</span>
              <span className="cd-burn__tick" style={{ left: zoneLeft(TIME_TONE_DAYS.warning) + "%" }}>120</span>
              <span className="cd-burn__tick" style={{ left: zoneLeft(TIME_TONE_DAYS.danger) + "%" }}>30</span>
              <span className="cd-burn__tick cd-burn__tick--last" style={{ left: "100%" }}>0</span>
            </div>
            <div className="cd-burn__legend">
              <span>One bar per open claim, height by amount claimed, up to {formatMoney(maxClaimed)}.</span>
              <span>Amber from {TIME_TONE_DAYS.warning} days left, red from {TIME_TONE_DAYS.danger}.</span>
            </div>
          </div>

          <div className="cd-section">
            <div className="cd-section__head">
              <h2 className="cd-h2">Nearest the wall</h2>
              <p className="cd-note">The three open claims closest to their time bar, whoever is holding them.</p>
            </div>
            <div className="cd-rows">
              {urgent.map((claim) => (
                <div className="cd-row" key={claim.id}>
                  <div className="cd-row__main">
                    <span className="cd-record__name">{claim.customer}</span>
                    <span className="cd-record__meta"><code>{claim.id}</code> · {formatMoney(claim.claimedCents)} claimed</span>
                    <span className="cd-record__meta">{CLAIM_FLAGS.awaitsAdjuster(claim) ? "On your desk" : "Waiting on " + waitingOn(claim)}</span>
                  </div>
                  <div className="cd-row__side">
                    <ClaimClock claim={claim} now={now} mini />
                    <Button variant="ghost" size="xs" onClick={() => onNavigate("/claims/" + claim.id)}>Open<Icon name="arrow-right" /></Button>
                  </div>
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>
    );
  }

  function QueueScreen({ data, now, desk, onNavigate, onNewClaim, onChase, pushToast }) {
    const [tab, setTab] = React.useState((desk && desk.queueTab) || DESK_DEFAULTS.queueTab);
    const [query, setQuery] = React.useState("");
    const claims = data.claims;
    /* One place decides where a claim opens from this screen, so the desk
       preference cannot disagree with itself between the table and the band. */
    const claimHref = (claim) => "/claims/" + claim.id + (desk && desk.openDecidable && CLAIM_FLAGS.isDecidable(claim) ? "/decision" : "");
    const spec = QUEUE_TABS.find((t) => t.value === tab);
    const inTab = claims.filter(spec.predicate);
    const rows = inTab.filter((c) => matches(c, query)).sort((a, b) => CLAIM_FLAGS.daysLeft(a, now) - CLAIM_FLAGS.daysLeft(b, now));
    const decidable = decidableClaims(claims);
    const stalled = stalledClaims(claims);

    return (
      <div className="cd-page">
        <PageHead
          path="/"
          owner={CLAIMS_USER}
          title="Work queue"
          lede={"Everything open on the " + CLAIMS_CARRIER.region + " desk. " + decidable.length + " of the " + claims.filter(CLAIM_FLAGS.awaitsAdjuster).length + " claims on your desk can be decided now" + (stalled.length ? " — " + stalled.map((c) => c.id).join(", ") + " is held by its own evidence." : ".")}
          actions={<><ExportMenu scope="Open claims" onExport={(format) => pushToast({ title: "Export started", description: "Open claims · " + format + " — we'll email it to " + CLAIMS_USER.name.split(" ")[0].toLowerCase() + "@corvenline.example" })} /><Button size="sm" onClick={() => onNewClaim(null)}>New claim</Button></>}
        />

        <BurnDownBand claims={claims} now={now} onNavigate={onNavigate} />

        <section className="cd-section">
          <div className="cd-filters">
            <div className="cd-filters__text">
              <Input
                size="sm" value={query} onChange={(e) => setQuery(e.target.value)}
                aria-label="Filter claims" placeholder="Filter by claimant, claim or container"
                startAddon={<Icon name="search" />}
              />
            </div>
            <Tabs value={tab} onValueChange={setTab}>
              <TabsList variant="underline" size="sm">
                {QUEUE_TABS.map((t) => (
                  <TabsTab key={t.value} value={t.value} size="sm">
                    {t.label}<span className="cd-tab-count">{claims.filter(t.predicate).length}</span>
                  </TabsTab>
                ))}
              </TabsList>
            </Tabs>
          </div>

          {rows.length === 0 ? (
            <Empty>
              <EmptyHeader>
                <EmptyMedia variant="icon"><Icon name="search-x" size={18} /></EmptyMedia>
                <EmptyTitle>No claim matches “{query}”</EmptyTitle>
                <EmptyDescription>{formatPlural(inTab.length, "claim")} sit under {spec.label.toLowerCase()}. Clear the filter to see them.</EmptyDescription>
              </EmptyHeader>
              <EmptyContent>
                <Button onClick={() => setQuery("")}>Clear filter</Button>
              </EmptyContent>
            </Empty>
          ) : (
            <div className="cd-table-wrap">
              <Table className="cd-tbl">
                <TableHeader>
                  <TableRow>
                    <TableHead>Claim</TableHead>
                    <TableHead className="cd-drop-lg">Cargo</TableHead>
                    <TableHead className="cd-num">Claimed</TableHead>
                    <TableHead className="cd-num">Payable</TableHead>
                    <TableHead>Status</TableHead>
                    <TableHead className="cd-drop-md">Time bar</TableHead>
                    <TableHead className="cd-actions"><span className="o-sr">Action</span></TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {rows.map((claim) => {
                    const recessed = CLAIM_FLAGS.isWaitingOnOthers(claim);
                    const payable = payableOf(claim);
                    const missing = CLAIM_FLAGS.missingMandatory(claim);
                    const decidableRow = CLAIM_FLAGS.isDecidable(claim);
                    const holdReason = missing.length
                      ? "Waiting on evidence — " + missing.map((m) => labelOf(DOCUMENT_TYPES, m).toLowerCase()).join(", ")
                      : null;
                    return (
                      <TableRow key={claim.id} className={recessed ? "cd-row-recessed" : ""}>
                        <TableCell>
                          <span className="cd-record">
                            <button type="button" className="cd-record__link" onClick={() => onNavigate(claimHref(claim))}>{claim.customer}</button>
                            <span className="cd-record__meta"><code>{claim.id}</code> · {claim.container}</span>
                          </span>
                        </TableCell>
                        <TableCell className="cd-drop-lg cd-muted">
                          <span className="cd-record">
                            <span>{claim.commodity}</span>
                            <span className="cd-record__meta">{formatPlural(claim.packages, "package")} · {formatCount(claim.weightKg)} kg</span>
                          </span>
                        </TableCell>
                        <TableCell className="cd-num cd-amount">{formatMoney(claim.claimedCents)}</TableCell>
                        <TableCell className="cd-num">
                          {claim.decision && claim.decision.outcome === "reject"
                            ? <span className="cd-muted">Nothing payable</span>
                            : payable === null
                              ? <span className="cd-muted">Not assessed</span>
                              : <span className="cd-amount">{formatMoney(payable)}</span>}
                        </TableCell>
                        <TableCell>
                          <span className="cd-record">
                            <StatusBadge values={CLAIM_STATUS} value={claim.status} />
                            {recessed ? <span className="cd-record__meta">Waiting on {waitingOn(claim)}</span> : null}
                            {!recessed && holdReason ? <span className="cd-record__meta">{holdReason}</span> : null}
                          </span>
                        </TableCell>
                        <TableCell className="cd-drop-md">
                          {CLAIM_FLAGS.isOpen(claim)
                            ? <ClaimClock claim={claim} now={now} mini />
                            : <span className="cd-muted cd-clock">Closed {formatWhen(claim.decision ? claim.decision.decidedAt : claim.claimedAt, now)}</span>}
                        </TableCell>
                        <TableCell className="cd-actions">
                          {decidableRow ? (
                            <Button size="xs" onClick={() => onNavigate("/claims/" + claim.id + "/decision")}>Record decision</Button>
                          ) : CLAIM_FLAGS.awaitsAdjuster(claim) ? (
                            <FloatingTip side="bottom" label={holdReason}>
                              <Button size="xs" disabled>Record decision</Button>
                            </FloatingTip>
                          ) : claim.status === "awaiting_documents" || claim.status === "awaiting_survey" ? (
                            <Button variant="outline" size="xs" onClick={() => onChase(claim)}>{claimTransitions(claim)[0].label}</Button>
                          ) : null}
                        </TableCell>
                      </TableRow>
                    );
                  })}
                </TableBody>
              </Table>
            </div>
          )}
          <div className="cd-foot">
            <span>Showing {rows.length} of {inTab.length} {spec.label.toLowerCase()}{query ? " matching “" + query + "”" : ""} · {formatPlural(claims.length, "claim")} on the desk</span>
            <span>Sorted by days left, soonest first.</span>
          </div>
        </section>
      </div>
    );
  }

  Object.assign(window, { QueueScreen, QUEUE_TABS });
})();
