/* Brief and match — who on the book fits this brand's ask, and who cannot take
   it at any price.
   Commit model: STAGED. The whole screen is one form: ticking creators builds a
   pitch, nothing leaves the desk until "Send pitch" is pressed, and Cancel
   appears once the selection differs from what was already pitched. There are
   no instant controls anywhere on it — "Chase the brand" and "Reopen brief"
   live on the briefs list, which owns them, so this screen holds exactly one
   commit model. "Pass on brief" opens a dialog, which carries its own.
   Data state: populated. A brief always has a roster to measure against.
   Actions derive from the record: a won brief shows where it landed and drops
   the pitch bar entirely; a closed one states why and links back.

   The exclusivity conflict is the thing this screen exists to prevent. It is
   stated three times, deliberately: as a full-width alert above everything, as
   a marked row in "Cannot take it", and as the reason on the disabled control
   itself. A conflict is a hazard, not a near miss, so it is never recessed. */
(() => {
  const {
    Button, Checkbox, Alert, AlertTitle, AlertDescription, AlertAction,
  } = window.OriginDesignSystem_7c998b;

  function Axis({ label, ok, value }) {
    return (
      <div className="mq-axis">
        <span className="mq-axis__label">{label}</span>
        <span className="mq-axis__mark" data-ok={ok ? "yes" : "no"}>
          <Icon name={ok ? "check" : "minus"} size={13} />{value}
        </span>
      </div>
    );
  }

  function FitRow({ row, brief, now, selected, onToggle, readOnly, variant }) {
    const creator = row.creator;
    const quote = row.quote;
    const disabledReason = row.blockedBecause || (quote.complete ? null : "No rate for " + quote.missing.map((k) => labelOf(DELIVERABLE_KINDS, k).toLowerCase()).join(" or "));
    const control = readOnly ? null : disabledReason ? (
      <FloatingTip side="left" label={disabledReason}>
        <span><Checkbox disabled checked={false} aria-label={"Cannot pitch " + creator.name + " — " + disabledReason} /></span>
      </FloatingTip>
    ) : (
      <Checkbox checked={selected} onCheckedChange={() => onToggle(creator.id)} aria-label={"Pitch " + creator.name + " at " + formatMoney(quote.totalCents)} />
    );
    return (
      <div className={"mq-fitrow" + (variant ? " mq-fitrow--" + variant : "")}>
        <Portrait creator={creator} size={56} />
        <div className="mq-who__text">
          <span className="mq-row__title">{creator.name}</span>
          <span className="mq-who__meta">@{creator.handle} · {creator.categories.map((c) => labelOf(CATEGORIES, c)).join(", ")}</span>
          {row.conflict ? (
            <span className="mq-note mq-bad"><strong>Exclusive to {row.conflict.brand}</strong> in {labelOf(CATEGORIES, row.conflict.category).toLowerCase()} until {formatAbsolute(row.conflict.until).split(",")[0]} — pitching them to {brief.brand} would breach it.</span>
          ) : row.blockedBecause ? (
            <span className="mq-note">{row.blockedBecause}</span>
          ) : null}
          {quote.complete ? null : (
            <span className="mq-note">{quote.missing.map((k) => labelOf(DELIVERABLE_KINDS, k).toLowerCase()).join(" and ")} is not on their rate card, so there is nothing to quote.</span>
          )}
        </div>
        <div className="mq-axes">
          <Axis label="Audience" ok={row.axes.audience} value={formatFollowers(row.reach)} />
          <Axis label="Category" ok={row.axes.category} value={row.axes.category ? labelOf(CATEGORIES, brief.category) : "Off"} />
          <Axis label="Rate" ok={row.axes.rate} value={quote.complete ? formatMoney(quote.totalCents) : "No rate"} />
        </div>
        <div className="mq-fitrow__quote">
          {quote.complete ? (
            <>
              <span className="mq-amount">{formatMoney(quote.totalCents)}</span>
              <span className="mq-row__meta">{formatMoney(quote.organicCents)} organic{quote.usage.uplift ? " + " + formatMoney(quote.upliftCents) + " usage" : ""}</span>
            </>
          ) : (
            <span className="mq-muted">No quote</span>
          )}
        </div>
        <div className="mq-actions">{control}</div>
      </div>
    );
  }

  function BriefRail({ brief, groups, floor, now }) {
    const usage = usageOf(brief.usage);
    return (
      <aside className="mq-rail">
        <div className="mq-sheet mq-sheet--tight">
          <Eyebrow>What they are asking for</Eyebrow>
          <dl className="mq-specs">
            <dt>Budget</dt><dd className="mq-amount">{formatMoney(brief.budgetCents)}</dd>
            <dt>Audience</dt><dd>{formatFollowers(brief.audienceMin)}+ total</dd>
            <dt>Category</dt><dd>{labelOf(CATEGORIES, brief.category)}</dd>
            <dt>Wants</dt><dd><KindList deliverables={brief.deliverables} /></dd>
            <dt>Usage</dt><dd>{usage.label}{usage.months ? ", " + usage.months + " months" : ""}{usage.uplift ? " · +" + Math.round(usage.uplift * 100) + "% on the fee" : ""}</dd>
            <dt>Window</dt><dd>{formatAbsolute(brief.liveFromAt).split(",")[0]} – {formatAbsolute(brief.liveToAt).split(",")[0]}</dd>
            <dt>Answer by</dt><dd>{formatAbsolute(brief.respondByAt).split(",")[0]}</dd>
          </dl>
        </div>
        <div className="mq-sheet mq-sheet--tight">
          <Eyebrow>How the book measures up</Eyebrow>
          <div className="mq-lg">
            <LedgerRow label="Fits every axis" value={groups.fits.length} hint="Audience, category and rate, and free in the window." />
            <LedgerRow label="Cannot take it" value={groups.blocked.length} hint="Booked across the window, paused, or under an exclusivity." />
            <LedgerRow label="Off brief" value={groups.offBrief.length} hint="Free to take it, but short on at least one axis." />
            <LedgerRow label="Cheapest complete quote" value={floor === null ? "—" : formatMoney(floor)} variant="sub" />
          </div>
          <p className="mq-note">Availability is judged against {formatAbsolute(brief.liveFromAt).split(",")[0]}, the day the brand wants to go live — not against today.</p>
        </div>
      </aside>
    );
  }

  function MatchScreen({ brief, data, now, onNavigate, onBriefTransition, onSendPitch }) {
    const initial = brief.pitched || [];
    const [selected, setSelected] = React.useState(initial);
    React.useEffect(() => { setSelected(brief.pitched || []); }, [brief.id, brief.status]);

    const groups = matchGroups(data.creators, brief, now, data.deals);
    const floor = rosterFloor(data.creators, brief);
    const open = BRIEF_FLAGS.isOpen(brief);
    const deal = dealForBrief(data.deals, brief);
    const byId = (id) => groups.all.find((r) => r.creator.id === id);
    const chosen = selected.map(byId).filter(Boolean);
    const quoted = sumOf(chosen.filter((r) => r.quote.complete), (r) => r.quote.totalCents);
    const stretch = chosen.filter((r) => !r.fits);
    const dirty = selected.slice().sort().join(",") !== initial.slice().sort().join(",");
    const toggle = (id) => setSelected((list) => (list.indexOf(id) > -1 ? list.filter((x) => x !== id) : list.concat([id])));

    const passTransition = briefTransitions(brief, groups.fits.length).find((t) => t.id === "pass_brief");

    return (
      <div className="mq-page mq-page--tight">
        <RecordHead
          crumb={<Crumbs path="/briefs/:id" params={{ id: brief.id }} labels={{ "/briefs/:id": brief.brand }} />}
          id={brief.id + " · received " + formatAbsolute(brief.receivedAt).split(",")[0]}
          status={<StatusBadge values={BRIEF_STATUS} value={brief.status} />}
          title={brief.brand + " — " + brief.title}
          lede={brief.ask}
          actions={
            <div className="mq-actions__row">
              {open && passTransition ? <Button variant="outline" size="sm" onClick={() => onBriefTransition(brief, passTransition)}>{passTransition.label}</Button> : null}
              <Button variant="ghost" size="sm" onClick={() => onNavigate("/brands/" + brief.brandId)}>{brief.brand}'s file<Icon name="arrow-right" /></Button>
            </div>
          }
        />

        {groups.conflicts.length ? (
          <Alert variant="error">
            <AlertTitle>
              {groups.conflicts.length === 1
                ? groups.conflicts[0].creator.name + " cannot be pitched to " + brief.brand
                : groups.conflicts.length + " creators cannot be pitched to " + brief.brand}
            </AlertTitle>
            <AlertDescription>
              {groups.conflicts.map((r) => (
                <span key={r.creator.id}>
                  {r.creator.name} signed an exclusivity with <strong>{r.conflict.brand}</strong> in {labelOf(CATEGORIES, r.conflict.category).toLowerCase()} on {formatAbsolute(r.conflict.signedAt).split(",")[0]}, running until <strong>{formatAbsolute(r.conflict.until).split(",")[0]}</strong> — {formatCountdown(r.conflict.until, now)}. {brief.brand} is a {labelOf(CATEGORIES, brief.category).toLowerCase()} brand, so any pitch is a breach.{" "}
                </span>
              ))}
            </AlertDescription>
          </Alert>
        ) : null}

        {deal ? (
          <Alert variant="success">
            <AlertTitle>Placed with {creatorById(data.creators, deal.creatorId).name}</AlertTitle>
            <AlertDescription>Agreed on {formatAbsolute(deal.agreedAt).split(",")[0]} at {formatMoney(deal.feeCents)}. The pitch is closed; the deal is where the work is now.</AlertDescription>
            <AlertAction><Button size="sm" onClick={() => onNavigate("/deals/" + deal.id)}>Open the deal<Icon name="arrow-right" /></Button></AlertAction>
          </Alert>
        ) : null}

        {!open && !deal ? (
          <Alert>
            <AlertTitle>{brief.status === "passed" ? "We passed on this brief" : "The brand went elsewhere"}</AlertTitle>
            <AlertDescription>
              {brief.status === "passed"
                ? labelOf(PASS_REASONS, brief.passReason) + " — " + brief.passNote + " Recorded " + formatAbsolute(brief.passedAt).split(",")[0] + "."
                : brief.lostNote + " Closed " + formatAbsolute(brief.lostAt).split(",")[0] + "."}
              {" "}Reopening it is done from the briefs list.
            </AlertDescription>
          </Alert>
        ) : null}

        <div className="mq-split mq-split--rail">
          <BriefRail brief={brief} groups={groups} floor={floor} now={now} />

          <div className="mq-col">
            <section className="mq-section">
              <div className="mq-section__head">
                <h2 className="mq-h2">Fits the brief<span className="mq-tab-count">{groups.fits.length}</span></h2>
                <p className="mq-note">Clears the audience floor, works in {labelOf(CATEGORIES, brief.category).toLowerCase()}, quotes inside the budget, and is free across the brand's window.</p>
              </div>
              {groups.fits.length === 0 ? (
                <p className="mq-note">Nobody on the book clears all three axes for this one. {groups.blocked.length ? "Of the " + groups.blocked.length + " who cannot take it, " + groups.conflicts.length + " is barred by an exclusivity rather than a diary." : ""} The honest answer to {brief.brand} is no.</p>
              ) : (
                <div className="mq-rows">
                  {groups.fits.map((row) => (
                    <FitRow key={row.creator.id} row={row} brief={brief} now={now} readOnly={!open}
                      selected={selected.indexOf(row.creator.id) > -1} onToggle={toggle} />
                  ))}
                </div>
              )}
            </section>

            {groups.blocked.length ? (
              <section className="mq-section">
                <div className="mq-section__head">
                  <h2 className="mq-h2">Cannot take it<span className="mq-tab-count">{groups.blocked.length}</span></h2>
                  <p className="mq-note">Not a matter of fit. An exclusivity is a contract we signed; a booking is a promise we made.</p>
                </div>
                <div className="mq-rows">
                  {groups.blocked.map((row) => (
                    <FitRow key={row.creator.id} row={row} brief={brief} now={now} readOnly={!open}
                      variant={row.conflict ? "blocked" : "off"} selected={false} onToggle={toggle} />
                  ))}
                </div>
              </section>
            ) : null}

            {groups.offBrief.length ? (
              <section className="mq-section">
                <div className="mq-section__head">
                  <h2 className="mq-h2">Off brief<span className="mq-tab-count">{groups.offBrief.length}</span></h2>
                  <p className="mq-note">Free to take it, short on at least one axis. Pitch them anyway if you can argue it — the pitch bar will say what you are stretching.</p>
                </div>
                <div className="mq-rows">
                  {groups.offBrief.map((row) => (
                    <FitRow key={row.creator.id} row={row} brief={brief} now={now} readOnly={!open}
                      variant="off" selected={selected.indexOf(row.creator.id) > -1} onToggle={toggle} />
                  ))}
                </div>
              </section>
            ) : null}
          </div>
        </div>

        {open ? (
          <div className="mq-pitchbar">
            <div className="mq-pitchbar__text">
              <strong>{chosen.length === 0 ? "Nobody selected" : chosen.length + (chosen.length === 1 ? " creator" : " creators")}</strong>
              {chosen.length ? <span className="mq-amount">{formatMoney(quoted)} quoted against {formatMoney(brief.budgetCents)}</span> : <span className="mq-muted">Tick the creators you want to put in front of {brief.brand}.</span>}
              {stretch.length ? <span className="mq-warn">{stretch.length} of them {stretch.length === 1 ? "is" : "are"} off brief on {stretch[0].missedAxes.join(" and ")}</span> : null}
              {brief.pitched && brief.pitched.length ? <span className="mq-muted">Pitched {formatAbsolute(brief.pitchedAt).split(",")[0]}</span> : null}
            </div>
            <div className="mq-actions__row">
              {dirty ? <Button variant="outline" size="sm" onClick={() => setSelected(initial)}>Cancel</Button> : null}
              <Button size="sm" disabled={!dirty || chosen.length === 0} onClick={() => onSendPitch(brief, selected, quoted)}>
                Send pitch to {brief.brand}
              </Button>
            </div>
          </div>
        ) : null}
      </div>
    );
  }

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