/* Deliverables — everything in flight, across every deal.
   Commit model: INSTANT. Each control confirms itself: submitting, approving
   and chasing apply immediately and raise an undo toast; recording revisions
   and marking a post published open staged dialogs, which carry their own
   model. No Save button.
   Data state: populated. The empty branch is one conditional and never renders
   beside rows.
   Scope: every deliverable on every deal, whatever the contract's state. The
   ladder shows three weeks; the sections below show all of them, and each
   section runs its own predicate rather than slicing the list.
   Recession: work sitting with the brand is recessed — muted surface, no
   primary control, and the row names who is being waited on. Its transitions
   stay reachable in the row menu, because recording what the brand said is
   still our job. Published work is not recessed: finished is not blocked.
   Primary display: the week ladder — the only calendar in the product, and the
   only place a due date is shown as a position rather than a number. */
(() => {
  const {
    Button, MenuItem, Empty, EmptyHeader, EmptyMedia, EmptyTitle, EmptyDescription,
  } = window.OriginDesignSystem_7c998b;

  const DAY = 864e5;
  const LADDER_WEEKS = 3;

  const startOfDay = (ts) => { const d = new Date(ts); d.setHours(0, 0, 0, 0); return d.getTime(); };
  /* The Monday of the week before this one — the ladder's left edge. */
  const ladderStart = (now) => {
    const today = startOfDay(now);
    const dow = (new Date(today).getDay() + 6) % 7;
    return today - (dow + 7) * DAY;
  };

  const chipTone = (item, now) => {
    if (DELIVERABLE_FLAGS.isOverdue(item, now)) return "danger";
    if (item.status === "revisions_requested") return "warning";
    if (item.status === "published") return "success";
    if (DELIVERABLE_FLAGS.isWithBrand(item)) return "info";
    return "";
  };

  function WeekLadder({ rows, now, onNavigate }) {
    const start = ladderStart(now);
    const today = startOfDay(now);
    const days = [];
    for (let i = 0; i < LADDER_WEEKS * 7; i++) days.push(start + i * DAY);
    const inLadder = rows.filter((r) => startOfDay(r.item.dueAt) >= start && startOfDay(r.item.dueAt) < start + LADDER_WEEKS * 7 * DAY);
    const next = byDue(rows.filter((r) => startOfDay(r.item.dueAt) >= start + LADDER_WEEKS * 7 * DAY))[0];

    return (
      <div className="mq-section">
        <div className="mq-section__head">
          <h2 className="mq-h2">Three weeks</h2>
          <p className="mq-note">{inLadder.length} of {rows.length} deliverables fall due between {formatAbsolute(start).split(",")[0]} and {formatAbsolute(start + (LADDER_WEEKS * 7 - 1) * DAY).split(",")[0]}. Placed by due date, coloured by what state they are in.</p>
        </div>
        <div className="mq-weekhead" aria-hidden="true">
          <span>Last week</span><span>This week</span><span>Next week</span>
        </div>
        <div className="mq-week">
          {days.map((day) => {
            const onDay = byDue(inLadder.filter((r) => startOfDay(r.item.dueAt) === day));
            return (
              <div className="mq-week__day" key={day} data-work={onDay.length ? "yes" : "no"} data-past={day < today ? "yes" : "no"} data-today={day === today ? "yes" : "no"}>
                <span className="mq-week__date">{new Date(day).toLocaleDateString("en-GB", { weekday: "short", day: "numeric" })}</span>
                {onDay.map((r) => (
                  <button type="button" className="mq-chip" key={r.item.id} data-tone={chipTone(r.item, now)} onClick={() => onNavigate("/deliverables/" + r.item.id)}
                    aria-label={r.item.title + " for " + r.deal.brand + ", " + statusValue(DELIVERABLE_STATUS, r.item.status).label.toLowerCase()}>
                    <span className="mq-chip__who">{r.creator.name.split(" ")[0]} · {r.deal.brand}</span>
                    <span className="mq-chip__what">{r.item.title}</span>
                  </button>
                ))}
              </div>
            );
          })}
        </div>
        <div className="mq-foot">
          <span>Today is {formatAbsolute(now).split(",")[0]}. Red is over its due date, amber is back for revisions, blue is with the brand, green is live.</span>
          {next ? <span>Next after this window: {next.item.title} for {next.deal.brand}, {formatAbsolute(next.item.dueAt).split(",")[0]}.</span> : null}
        </div>
      </div>
    );
  }

  function WorkRow({ row, now, recessed, onTransition, onNavigate }) {
    const item = row.item;
    const transitions = deliverableTransitions(item);
    const primary = transitions.find((t) => t.primary);
    const rest = transitions.filter((t) => !t.primary);
    const waiting = deliverableWaitingOn(row);
    return (
      <div className={"mq-row" + (recessed ? " mq-row--recessed" : "")}>
        <Portrait creator={row.creator} size={36} />
        <div className="mq-row__main">
          <span className="mq-row__title">
            <button type="button" className="mq-link" onClick={() => onNavigate("/deliverables/" + item.id)}>{item.title}</button>
          </span>
          <span className="mq-row__meta">
            {row.creator.name} · <button type="button" className="mq-link" onClick={() => onNavigate("/brands/" + row.deal.brandId)}>{row.deal.brand}</button>
            {" · "}{item.quantity > 1 ? item.quantity + " × " : ""}{labelOf(DELIVERABLE_KINDS, item.kind)}
            {waiting ? " · waiting on " + waiting : ""}
            {DELIVERABLE_FLAGS.isLive(item) ? " · " + formatFollowers(item.metrics.reach) + " reached, " + formatCount(item.metrics.saves) + " saves" : ""}
          </span>
          {item.revisionNote ? <span className="mq-quote">“{item.revisionNote}” — {item.revisionBy}, {formatWhen(item.revisionAt, now)}</span> : null}
        </div>
        <div className="mq-row__side">
          <DueClock item={item} now={now} />
          <StatusBadge values={DELIVERABLE_STATUS} value={item.status} />
          {transitions.length === 0 ? null : recessed ? (
            <Floating align="end" width="14rem" label={"Actions for " + item.title}
              trigger={<Button variant="ghost" size="icon-xs" aria-label={"Actions for " + item.title}><Icon name="ellipsis" size={14} /></Button>}>
              {(close) => transitions.map((t) => <MenuItem key={t.id} onClick={() => { close(); onTransition(row, t); }}>{t.label}</MenuItem>)}
            </Floating>
          ) : (
            <>
              {primary ? <Button size="xs" onClick={() => onTransition(row, primary)}>{primary.label}</Button> : null}
              {rest.length ? (
                <Floating align="end" width="14rem" label={"More actions for " + item.title}
                  trigger={<Button variant="ghost" size="icon-xs" aria-label={"More actions for " + item.title}><Icon name="ellipsis" size={14} /></Button>}>
                  {(close) => rest.map((t) => <MenuItem key={t.id} onClick={() => { close(); onTransition(row, t); }}>{t.label}</MenuItem>)}
                </Floating>
              ) : null}
            </>
          )}
        </div>
      </div>
    );
  }

  function Group({ title, note, rows, now, recessed, onTransition, onNavigate }) {
    if (!rows.length) return null;
    return (
      <section className="mq-section">
        <div className="mq-section__head">
          <h2 className="mq-h2">{title}<span className="mq-tab-count">{rows.length}</span></h2>
          <p className="mq-note">{note}</p>
        </div>
        <div className="mq-rows">
          {rows.map((row) => (
            <WorkRow key={row.item.id} row={row} now={now} recessed={recessed} onTransition={onTransition} onNavigate={onNavigate} />
          ))}
        </div>
      </section>
    );
  }

  function DeliverablesScreen({ data, now, onNavigate, onDeliverableTransition, pushToast }) {
    const rows = allDeliverables(data.deals, data.creators);
    const needsYou = byDue(deliverablesNeedingAttention(rows, now));
    const withBrand = byDue(deliverablesWithBrand(rows));
    const ahead = byDue(deliverablesAhead(rows, now));
    const live = deliverablesLive(rows).slice().sort((a, b) => b.item.publishedAt - a.item.publishedAt);
    const overdue = needsYou.filter((r) => DELIVERABLE_FLAGS.isOverdue(r.item, now));

    if (rows.length === 0) {
      return (
        <div className="mq-page">
          <PageHead path="/deliverables" title="Deliverables" />
          <Empty>
            <EmptyHeader>
              <EmptyMedia variant="icon"><Icon name="clapperboard" size={18} /></EmptyMedia>
              <EmptyTitle>Nothing is in flight</EmptyTitle>
              <EmptyDescription>Deliverables appear here the moment a deal is agreed, whether or not the contract has come back.</EmptyDescription>
            </EmptyHeader>
          </Empty>
        </div>
      );
    }

    return (
      <div className="mq-page">
        <PageHead
          path="/deliverables"
          title="In flight"
          lede={needsYou.length
            ? needsYou.length + " of " + rows.length + " deliverables need you this week — " + (overdue.length ? overdue.length + (overdue.length === 1 ? " past its due date, " : " past their due date, ") : "") + "the rest due inside " + AGENCY_POLICY.dueSoonDays + " days. " + withBrand.length + " " + (withBrand.length === 1 ? "is" : "are") + " with a brand and cannot move until they answer."
            : "Nothing needs you this week. " + withBrand.length + " with a brand, " + ahead.length + " scheduled ahead, " + live.length + " live."}
          actions={<ExportMenu scope="All deliverables" onExport={(format) => pushToast({ title: "Export started", description: "Deliverables · " + format + " — we'll email it to " + MARQUE_USER.name.split(" ")[0].toLowerCase() + "@marque.example" })} />}
        />

        <WeekLadder rows={rows} now={now} onNavigate={onNavigate} />

        <Group
          title="Needs you" rows={needsYou} now={now} onTransition={onDeliverableTransition} onNavigate={onNavigate}
          note="Back for revisions, past its due date, or due inside the week. This is the count on the Deliverables tab."
        />
        <Group
          title="With the brand" rows={withBrand} now={now} recessed onTransition={onDeliverableTransition} onNavigate={onNavigate}
          note="Submitted and waiting on an answer. Nothing here is late — we handed it over on time and the clock is theirs."
        />
        <Group
          title="Scheduled ahead" rows={ahead} now={now} onTransition={onDeliverableTransition} onNavigate={onNavigate}
          note={"Due more than " + AGENCY_POLICY.dueSoonDays + " days out. Chasing early is how a shoot day gets moved cheaply."}
        />
        <Group
          title="Live" rows={live} now={now} onTransition={onDeliverableTransition} onNavigate={onNavigate}
          note="Published and measured. Reach and saves come from the post, and feed the campaign's promise on Performance."
        />

        <div className="mq-foot">
          <span>{rows.length} deliverables across {data.deals.length} deals · {needsYou.length} need you, {withBrand.length} with a brand, {ahead.length} ahead, {live.length} live</span>
          <span>A due date reads as a countdown; the exact date is on hover.</span>
        </div>
      </div>
    );
  }

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