// ============================================================
// Nami Order Portal — Deal detail view
// ============================================================

const ROLE_LABEL_DD = { admin: "Admin", manager: "Manager", legal: "Legal", ae: "AE" };
const userHasRole = (user, role) =>
  !!user && Array.isArray(user.roles) && user.roles.includes(role);

const DealDetail = ({
  deal, user, onBack, onEdit, onSendModal, onViewPdf, onViewAsCustomer,
  onSubmitForLegal, onLegalApprove, onLegalReject, onPostInternalComment,
  onRevokeReviewLink, onResolveComment,
  onResolveException, onRequestException,
  customerEdits, customerEditedAt, onApplyCustomerEdits, onDiscardCustomerEdits,
}) => {
  const isLegalReviewer = userHasRole(user, "legal") || userHasRole(user, "admin");
  const isDealDeskReviewer = userHasRole(user, "manager") || userHasRole(user, "admin");
  const isPendingLegal = deal.status === "legal";
  const legalFlags = window.NAMI_DATA.dealLegalFlags(deal);
  const needsLegal = window.NAMI_DATA.dealNeedsLegal(deal);
  const showLegalTab = isPendingLegal || (legalFlags.length > 0 && isLegalReviewer);
  const exceptions = deal.exceptions || [];
  const pendingExceptions = exceptions.filter((e) => e.status === "requested");
  const showExceptionsTab = exceptions.length > 0 || (isDealDeskReviewer && pendingExceptions.length > 0);

  // Default to the most relevant tab for the viewer's role + deal state.
  const defaultTab =
    isPendingLegal ? "legal" :
    deal.status === "review" ? "comments" :
    "config";
  const [tab, setTab] = React.useState(defaultTab);
  const variants = window.NAMI_DATA.VARIANTS;

  const appliedVariants = variants
    .map((v) => {
      const val = (deal.variants || {})[v.id];
      if (val == null || val === false || (Array.isArray(val) && !val.length)) return null;
      return { variant: v, value: val };
    })
    .filter(Boolean);

  const isRenewal = deal.status === "renewal";
  const isActive = deal.status === "active";
  const isInReview = deal.status === "review";
  const comments = deal.comments || [];
  const openCount = comments.filter((c) => c.status === "open").length;

  return (
    <div className="main__inner">
      <button className="detail-header__back" onClick={onBack}>
        <Icon name="chevronLeft" size={14} /> Deals
      </button>

      <div className="detail-header">
        <div className="detail-header__top">
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 6 }}>
              <DealLogo deal={deal} size={36} />
              <h1>{deal.name}</h1>
            </div>
            <div className="detail-header__meta">
              <span>{deal.customer}</span>
              <span className="dot" />
              <StatusBadge status={deal.status} />
              <span className="dot" />
              <span>{deal.ae}</span>
              <span className="dot" />
              <span>Updated {deal.updated}</span>
            </div>
          </div>

          <div className="flex gap-3">
            {isInReview && (
              <button className="btn btn--ghost btn--sm" onClick={onViewAsCustomer}>
                <Icon name="eye" size={14} /> View as customer
              </button>
            )}
            <button className="btn btn--ghost btn--sm" onClick={() => onViewPdf(deal.id)}>
              <Icon name="file" size={14} /> Open PDF
            </button>
            <button className="btn btn--outline btn--sm" onClick={onEdit}>
              <Icon name="edit" size={14} /> Edit
            </button>
            {(deal.status === "draft" || deal.status === "approved") && (
              <button className="btn btn--alloy btn--sm" onClick={onSendModal}>
                <Icon name="send" size={14} /> Send draft
              </button>
            )}
            {isInReview && (
              <button className="btn btn--outline btn--sm" onClick={onSendModal} title="Re-send the draft (e.g. updated terms after change requests).">
                <Icon name="send" size={14} /> Re-send draft
              </button>
            )}
          </div>
        </div>

        <div className="detail-header__stats">
          <div className="detail-header__stat">
            <div className="label">Total contract value</div>
            <div className="value">{money(deal.tcv)}</div>
          </div>
          <div className="detail-header__stat">
            <div className="label">Trim</div>
            <div className="value"><TrimChip trim={deal.trim} /></div>
          </div>
          <div className="detail-header__stat">
            <div className="label">Term</div>
            <div className="value">{deal.termYears}yr</div>
          </div>
          <div className="detail-header__stat">
            <div className="label">{isActive || isRenewal ? "Ends" : "Starts"}</div>
            <div className="value">{fmtDate(isActive || isRenewal ? deal.endDate : deal.startDate)}</div>
          </div>
        </div>
      </div>

      <div className="tabs">
        <button className={tab === "config" ? "is-active" : ""} onClick={() => setTab("config")}>Configuration</button>
        <button className={tab === "variants" ? "is-active" : ""} onClick={() => setTab("variants")}>Variants ({appliedVariants.length})</button>
        {(isInReview || comments.length > 0) && (
          <button className={tab === "comments" ? "is-active" : ""} onClick={() => setTab("comments")}>
            Comments
            {openCount > 0 && (
              <span style={{ marginLeft: 6, fontSize: 10, padding: "1px 7px", borderRadius: 9999, background: "var(--accent-yellow)", color: "#5a3800", fontWeight: 700 }}>
                {openCount}
              </span>
            )}
          </button>
        )}
        {showLegalTab && (
          <button
            className={tab === "legal" ? "is-active" : ""}
            onClick={() => setTab("legal")}
          >
            Legal review
            {legalFlags.length > 0 && (
              <span style={{ marginLeft: 6, fontSize: 10, padding: "1px 7px", borderRadius: 9999, background: "rgba(255,193,7,0.25)", color: "#8a5d00", fontWeight: 700 }}>
                {legalFlags.length}
              </span>
            )}
          </button>
        )}
        {showExceptionsTab && (
          <button
            className={tab === "exceptions" ? "is-active" : ""}
            onClick={() => setTab("exceptions")}
          >
            Exceptions
            {pendingExceptions.length > 0 && (
              <span style={{ marginLeft: 6, fontSize: 10, padding: "1px 7px", borderRadius: 9999, background: "rgba(11,74,142,0.18)", color: "var(--blue-alloy)", fontWeight: 700 }}>
                {pendingExceptions.length}
              </span>
            )}
          </button>
        )}
        <button className={tab === "preview" ? "is-active" : ""} onClick={() => setTab("preview")}>Preview</button>
        <button className={tab === "activity" ? "is-active" : ""} onClick={() => setTab("activity")}>Activity log</button>
      </div>

      <div className="detail-grid">
        <div>
          {tab === "config" && <ConfigTab deal={deal} />}
          {tab === "variants" && <VariantsTab applied={appliedVariants} />}
          {tab === "preview" && (
            <div className="card" style={{ padding: 0, overflow: "hidden" }}>
              <div style={{ padding: "16px 20px", borderBottom: "1px solid var(--strokes)", display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                <div style={{ fontSize: 13, fontWeight: 700, color: "var(--dark-grey)", textTransform: "uppercase", letterSpacing: "0.06em" }}>Service Order package</div>
                <button className="btn btn--outline btn--sm" onClick={() => onViewPdf(deal.id)}>
                  <Icon name="eye" size={13} /> Open full preview
                </button>
              </div>
              {/* Embed the same 7+ page OrderFormPDF the customer sees, scaled
                  down so it fits within the deal-detail card without scrolling
                  off the page. The component is the source of truth for the
                  Service Order package, so the AE preview can't drift. */}
              <div className="pdf-embed" style={{ maxHeight: 720, overflowY: "auto", background: "var(--alice-grey)" }}>
                <div style={{ transform: "scale(0.72)", transformOrigin: "top center", width: "calc(100% / 0.72)", padding: "16px 0 32px" }}>
                  <window.OrderFormPDF
                    deal={deal}
                    coverTreatment="smoke"
                    embedded={true}
                  />
                </div>
              </div>
            </div>
          )}
          {tab === "comments" && <CommentsTab deal={deal} comments={comments} onViewAsCustomer={onViewAsCustomer} onResolveComment={onResolveComment} />}
          {tab === "exceptions" && (
            <ExceptionsTab
              deal={deal}
              user={user}
              isDealDeskReviewer={isDealDeskReviewer}
              exceptions={exceptions}
              onResolveException={onResolveException}
              onRequestException={onRequestException}
            />
          )}
          {tab === "legal" && (
            <LegalReviewTab
              deal={deal}
              user={user}
              isLegalReviewer={isLegalReviewer}
              flags={legalFlags}
              onApprove={onLegalApprove}
              onReject={onLegalReject}
              onPostComment={onPostInternalComment}
            />
          )}
          {tab === "activity" && <ActivityTab deal={deal} />}
        </div>

        <aside>
          {isRenewal && (
            <div className="renewal-card mb-4">
              <div className="label">Renewal due in</div>
              <div className="days">{deal.renewalDays}<span style={{ fontSize: 14, color: "var(--dark-grey)", marginLeft: 6, fontWeight: 500 }}>days</span></div>
              <div className="desc">Current term ends {fmtDate(deal.endDate)}. Customer's renewal anchor is the same trim ({deal.trim}), 2-year term, 20% volume escalator pre-loaded.</div>
              <button className="btn btn--alloy btn--sm" style={{ width: "100%" }}>
                <Icon name="refresh" size={13} /> Create renewal deal
              </button>
            </div>
          )}

          {deal.status === "sent" && (
            <div className="card card--tight mb-4" style={{ background: "rgba(19,116,222,0.04)", borderColor: "rgba(19,116,222,0.25)" }}>
              <div style={{ fontSize: 11, fontWeight: 700, color: "var(--blue-alloy)", textTransform: "uppercase", letterSpacing: "0.06em", marginBottom: 6 }}>Sent to DocuSign</div>
              <div style={{ fontSize: 13.5, color: "var(--navy)", fontWeight: 600, marginBottom: 4 }}>Awaiting customer signature</div>
              <div style={{ fontSize: 12, color: "var(--dark-grey)", lineHeight: 1.5 }}>
                Envelope <span style={{ fontFamily: "ui-monospace, Menlo, monospace", color: "var(--navy)" }}>4b8a-…</span> sent {deal.sentAt || "May 11, 2026 · 11:24 AM"} to <strong>{deal.sentTo || "legal@customer.com"}</strong>.
              </div>
              <button className="btn btn--ghost btn--sm" style={{ marginTop: 10, width: "100%" }}>
                Resend reminder
              </button>
            </div>
          )}

          {isInReview && (
            <InReviewCard
              deal={deal}
              openCount={openCount}
              onViewAsCustomer={onViewAsCustomer}
              onRevokeReviewLink={onRevokeReviewLink}
            />
          )}

          {isInReview && customerEdits && Object.keys(customerEdits).length > 0 && (
            <CustomerEditsCard
              deal={deal}
              edits={customerEdits}
              editedAt={customerEditedAt}
              onApply={onApplyCustomerEdits}
              onDiscard={onDiscardCustomerEdits}
            />
          )}

          {deal.stripeAutoInvoice && (deal.status === "draft" || isInReview || deal.status === "sent" || deal.status === "signed" || deal.status === "active") && (
            <div className="card card--tight mb-4" style={{ background: "rgba(99,91,255,0.04)", borderColor: "rgba(99,91,255,0.25)" }}>
              <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 8 }}>
                <div style={{ width: 28, height: 28, borderRadius: 8, background: "#635BFF", color: "#fff", display: "flex", alignItems: "center", justifyContent: "center", fontWeight: 800, fontSize: 12 }}>S</div>
                <div>
                  <div style={{ fontSize: 11, fontWeight: 700, color: "#635BFF", textTransform: "uppercase", letterSpacing: "0.06em" }}>Stripe trigger</div>
                  <div style={{ fontSize: 13, color: "var(--navy)", fontWeight: 600 }}>{isActive ? "First invoice sent" : "Queued for Effective Date"}</div>
                </div>
              </div>
              <div style={{ fontSize: 12, color: "var(--dark-grey)", lineHeight: 1.5 }}>
                On {fmtDate(deal.startDate)}, an invoice for <strong style={{ color: "var(--navy)" }}>{money(((deal.commits || [0])[0] / 1000) * (deal.cpm || window.NAMI_DATA.TRIM_TIERS[deal.trim || "premier"].cpmRepresentative) / (deal.cadence === "quarterly" ? 4 : 1))}</strong> will issue to <strong>{deal.billingContact?.email || "ap@customer.com"}</strong>.
              </div>
            </div>
          )}

          {deal.status === "legal" && (
            <div className="card card--tight mb-4" style={{ background: "rgba(255,198,105,0.1)", borderColor: "rgba(255,198,105,0.5)" }}>
              <div style={{ fontSize: 11, fontWeight: 700, color: "#8a5800", textTransform: "uppercase", letterSpacing: "0.06em", marginBottom: 6 }}>Pending Legal</div>
              <div style={{ fontSize: 13.5, color: "var(--navy)", fontWeight: 600, marginBottom: 4 }}>
                {isLegalReviewer ? "Awaiting your review" : "Routed for review"}
              </div>
              <div style={{ fontSize: 12, color: "var(--dark-grey)", lineHeight: 1.5 }}>
                {deal.legalReason || "A non-pre-approved variant was requested. Legal will respond within 2 business days."}
              </div>
              {deal.legalSubmittedAt && (
                <div style={{ fontSize: 11.5, color: "var(--dark-grey)", marginTop: 6 }}>
                  Submitted {deal.legalSubmittedAt}
                </div>
              )}
              <button
                className="btn btn--outline btn--sm"
                style={{ width: "100%", marginTop: 10 }}
                onClick={() => setTab("legal")}
              >
                <Icon name="warn" size={13} />
                {isLegalReviewer ? "Open legal review" : "View flags + thread"}
              </button>
            </div>
          )}

          {needsLegal && deal.status === "draft" && (
            <div className="card card--tight mb-4" style={{ background: "rgba(255,198,105,0.08)", borderColor: "rgba(255,198,105,0.4)" }}>
              <div style={{ fontSize: 11, fontWeight: 700, color: "#8a5800", textTransform: "uppercase", letterSpacing: "0.06em", marginBottom: 6 }}>Legal flag</div>
              <div style={{ fontSize: 13.5, color: "var(--navy)", fontWeight: 600, marginBottom: 4 }}>
                {legalFlags.length} variant{legalFlags.length === 1 ? "" : "s"} need counsel sign-off
              </div>
              <div style={{ fontSize: 12, color: "var(--dark-grey)", lineHeight: 1.5 }}>
                You can't send this deal to the customer until Legal approves the flagged items.
              </div>
              <button
                className="btn btn--alloy btn--sm"
                style={{ width: "100%", marginTop: 10 }}
                onClick={onSubmitForLegal}
              >
                <Icon name="send" size={13} /> Submit for legal review
              </button>
            </div>
          )}

          <div className="card card--tight mb-4">
            <div style={{ fontSize: 11, fontWeight: 700, color: "var(--dark-grey)", textTransform: "uppercase", letterSpacing: "0.06em", marginBottom: 10 }}>Owner</div>
            <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
              <div style={{ width: 32, height: 32, borderRadius: 9999, background: "var(--gradient-navy)", color: "#fff", display: "flex", alignItems: "center", justifyContent: "center", fontWeight: 700, fontSize: 11 }}>
                {(deal.ae || "S K").split(" ").map(n => n[0]).join("")}
              </div>
              <div>
                <div style={{ fontSize: 13.5, fontWeight: 600, color: "var(--navy)" }}>{deal.ae}</div>
                <div style={{ fontSize: 12, color: "var(--dark-grey)" }}>Account Executive</div>
              </div>
            </div>
          </div>

          <div className="card card--tight">
            <div style={{ fontSize: 11, fontWeight: 700, color: "var(--dark-grey)", textTransform: "uppercase", letterSpacing: "0.06em", marginBottom: 10 }}>Quick actions</div>
            <div className="flex-col gap-2">
              <button className="btn btn--ghost btn--sm" style={{ justifyContent: "flex-start" }}>
                <Icon name="copy" size={14} /> Duplicate deal
              </button>
              <button className="btn btn--ghost btn--sm" style={{ justifyContent: "flex-start" }}>
                <Icon name="files" size={14} /> Export config (JSON)
              </button>
              <button className="btn btn--ghost btn--sm" style={{ justifyContent: "flex-start", color: "var(--accent-red)" }}>
                <Icon name="archive" size={14} /> Archive
              </button>
            </div>
          </div>
        </aside>
      </div>
    </div>
  );
};

const ConfigTab = ({ deal }) => {
  const trims = window.NAMI_DATA.TRIM_TIERS;
  const t = trims[deal.trim || "premier"];

  return (
    <div className="card">
      <div className="kv-section">
        <h3>Customer</h3>
        <div className="kv-grid">
          <div className="kv"><span className="kv__label">Legal entity</span><span className="kv__value">{deal.customer || "—"}</span></div>
          <div className="kv"><span className="kv__label">Address</span><span className="kv__value">{deal.customerAddress || "—"}</span></div>
          <div className="kv"><span className="kv__label">Primary contact</span><span className="kv__value">{deal.primaryContact?.name || "—"}</span></div>
          <div className="kv"><span className="kv__label">Contact email</span><span className="kv__value">{deal.primaryContact?.email || "—"}</span></div>
          <div className="kv"><span className="kv__label">Authorized signer</span><span className="kv__value">{deal.contractAdmin?.name || "—"}{deal.contractAdmin?.title ? ` — ${deal.contractAdmin.title}` : ""}</span></div>
          <div className="kv"><span className="kv__label">A/P email</span><span className="kv__value">{deal.billingContact?.email || "—"}</span></div>
          <div className="kv"><span className="kv__label">Legal Notices</span><span className="kv__value">{deal.noticeAddress || "—"}</span></div>
        </div>
      </div>

      <div className="section-divider" />

      <div className="kv-section">
        <h3>Services</h3>
        <div className="kv-grid">
          <div className="kv"><span className="kv__label">Trim</span><span className="kv__value"><TrimChip trim={deal.trim} /></span></div>
          <div className="kv"><span className="kv__label">Support level</span><span className="kv__value" style={{ textTransform: "capitalize" }}>{deal.support || "—"}</span></div>
          <div className="kv"><span className="kv__label">Add-ons</span><span className="kv__value">{(deal.addons || []).join(", ") || "None"}</span></div>
        </div>
      </div>

      <div className="section-divider" />

      <div className="kv-section">
        <h3>Commercial terms</h3>
        <div className="kv-grid">
          <div className="kv"><span className="kv__label">Term length</span><span className="kv__value">{deal.termYears || "—"} {(deal.termYears || 1) === 1 ? "year" : "years"}</span></div>
          <div className="kv"><span className="kv__label">Start date</span><span className="kv__value">{fmtDate(deal.startDate)}</span></div>
          <div className="kv"><span className="kv__label">End date</span><span className="kv__value">{fmtDate(deal.endDate)}</span></div>
          <div className="kv"><span className="kv__label">CPM rate</span><span className="kv__value">${(deal.cpm || t.cpmRepresentative).toFixed(2)}</span></div>
          <div className="kv"><span className="kv__label">Total contract value</span><span className="kv__value">{money(deal.tcv)}</span></div>
          <div className="kv"><span className="kv__label">Volume commits</span><span className="kv__value">{(deal.commits || []).map(fmtImpressions).join(" / ") || "—"}</span></div>
        </div>
      </div>

      <div className="section-divider" />

      <div className="kv-section">
        <h3>Payment</h3>
        <div className="kv-grid">
          <div className="kv"><span className="kv__label">Cadence</span><span className="kv__value" style={{ textTransform: "capitalize" }}>{deal.cadence || "—"}</span></div>
          <div className="kv"><span className="kv__label">Net terms</span><span className="kv__value">{deal.netTerms || "—"}</span></div>
          <div className="kv"><span className="kv__label">Currency</span><span className="kv__value">{deal.currency || "USD"}</span></div>
        </div>
      </div>
    </div>
  );
};

const VariantsTab = ({ applied }) => {
  if (!applied.length) {
    return (
      <div className="card" style={{ textAlign: "center", padding: 60 }}>
        <Icon name="files" size={32} color="var(--strokes)" />
        <div style={{ marginTop: 14, fontWeight: 600, color: "var(--navy)" }}>No variants applied</div>
        <div style={{ marginTop: 4, fontSize: 13, color: "var(--dark-grey)" }}>This deal uses the standard Terms of Service unmodified.</div>
      </div>
    );
  }
  return (
    <div className="flex-col gap-4">
      {applied.map(({ variant, value }, i) => {
        const lang = variant.langTemplate(value);
        return (
          <div key={variant.id} className="card">
            <div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 12, marginBottom: 8 }}>
              <div>
                <div style={{ fontSize: 11, color: "var(--dark-grey)", textTransform: "uppercase", letterSpacing: "0.06em", fontWeight: 700 }}>Amendment {i + 1} · {variant.section}</div>
                <div style={{ fontSize: 17, fontWeight: 700, color: "var(--navy)", marginTop: 4 }}>{variant.category}</div>
              </div>
              <div style={{ fontSize: 12.5, color: "var(--dark-grey)" }}>
                Selected: <strong style={{ color: "var(--navy)" }}>{summarizeValue(variant, value)}</strong>
              </div>
            </div>
            <div style={{ fontSize: 13, color: "var(--navy)", fontStyle: "italic", padding: "14px 18px", borderLeft: "3px solid var(--blue-alloy)", background: "var(--alice-grey)", borderRadius: "0 8px 8px 0", lineHeight: 1.6 }}>
              "{lang}"
            </div>
          </div>
        );
      })}
    </div>
  );
};

const summarizeValue = (variant, value) => {
  if (variant.kind === "radio") return variant.options.find((o) => o.value === value)?.label || value;
  if (variant.kind === "toggle") return value ? "Applied" : "Standard";
  if (variant.kind === "checkboxes") {
    return value.map((v) => variant.options.find((o) => o.value === v)?.label || v).join(", ");
  }
  return String(value);
};

const CommentsTab = ({ deal, comments, onViewAsCustomer, onResolveComment }) => {
  const [filter, setFilter] = React.useState("all");
  const [reply, setReply] = React.useState({});
  const filtered = comments.filter((c) => {
    if (filter === "open") return c.status === "open";
    if (filter === "resolved") return c.status !== "open";
    return true;
  });
  // group by anchor
  const groups = {};
  filtered.forEach((c) => {
    if (!groups[c.anchor]) groups[c.anchor] = { label: c.anchorLabel, comments: [] };
    groups[c.anchor].comments.push(c);
  });
  const groupKeys = Object.keys(groups);

  return (
    <div className="card" style={{ padding: 0, overflow: "hidden" }}>
      <div style={{ padding: "14px 20px", borderBottom: "1px solid var(--strokes)", display: "flex", alignItems: "center", justifyContent: "space-between" }}>
        <div style={{ display: "flex", gap: 4 }}>
          {["all", "open", "resolved"].map((f) => (
            <button
              key={f}
              className={f === filter ? "is-active" : ""}
              style={{
                background: f === filter ? "var(--alice-grey)" : "transparent",
                border: "1px solid var(--strokes)",
                borderRadius: 9999,
                padding: "5px 12px",
                fontSize: 12,
                fontWeight: 600,
                color: f === filter ? "var(--navy)" : "var(--dark-grey)",
                cursor: "pointer",
                textTransform: "capitalize",
              }}
              onClick={() => setFilter(f)}
            >
              {f} ({comments.filter((c) => f === "all" ? true : f === "open" ? c.status === "open" : c.status !== "open").length})
            </button>
          ))}
        </div>
        <button className="btn btn--outline btn--sm" onClick={onViewAsCustomer}>
          <Icon name="eye" size={13} /> Open as customer
        </button>
      </div>

      {groupKeys.length === 0 && (
        <div style={{ textAlign: "center", padding: 60, color: "var(--dark-grey)" }}>
          <Icon name="files" size={32} color="var(--strokes)" />
          {comments.length === 0 ? (
            <>
              <div style={{ marginTop: 14, fontWeight: 600, color: "var(--navy)" }}>
                {deal.status === "review"
                  ? "Awaiting customer feedback"
                  : "No customer comments on this deal"}
              </div>
              <div style={{ marginTop: 6, fontSize: 12.5, maxWidth: 360, marginLeft: "auto", marginRight: "auto", lineHeight: 1.5 }}>
                {deal.status === "review"
                  ? <>The link was sent to <strong>{deal.reviewSentTo || "the customer"}</strong>{deal.reviewSentAt ? ` on ${deal.reviewSentAt}` : ""}. Inline comments and decisions will land here as the customer works through the package.</>
                  : "Customer comments collected during a review round show up here. Send the package for review to start a thread."}
              </div>
              {deal.status === "review" && (
                <button className="btn btn--ghost btn--sm" style={{ marginTop: 16 }} onClick={onViewAsCustomer}>
                  <Icon name="eye" size={13} /> Open as customer
                </button>
              )}
            </>
          ) : (
            <>
              <div style={{ marginTop: 14, fontWeight: 600, color: "var(--navy)" }}>
                Nothing matches "{filter}"
              </div>
              <div style={{ marginTop: 6, fontSize: 12.5 }}>
                {filter === "open"
                  ? "All comments are resolved. Switch to All or Resolved to see them."
                  : "No resolved comments yet. Switch to All or Open to see the live thread."}
              </div>
            </>
          )}
        </div>
      )}

      <div className="flex-col" style={{ padding: groupKeys.length ? 20 : 0, gap: 18 }}>
        {groupKeys.map((anchor) => (
          <div key={anchor}>
            <div style={{ fontSize: 11, fontWeight: 700, color: "var(--blue-alloy)", textTransform: "uppercase", letterSpacing: "0.06em", marginBottom: 10 }}>
              {groups[anchor].label}
            </div>
            <div className="flex-col gap-2">
              {groups[anchor].comments.map((c) => (
                <div key={c.id} className={`comment is-${c.role}`}>
                  <div className="comment__head">
                    <div className="comment__avatar" style={{ background: c.role === "customer" ? "var(--nami-blue)" : "var(--kelp)" }}>
                      {c.author.split(" ").map((n) => n[0]).slice(0, 2).join("")}
                    </div>
                    <div className="comment__author">{c.author}</div>
                    <div className="comment__time">{c.time}</div>
                  </div>
                  <div className="comment__body">{c.body}</div>
                  <div style={{ display: "flex", gap: 6, marginTop: 8, alignItems: "center" }}>
                    <span className={`comment__status comment__status--${c.status}`} style={{ marginTop: 0 }}>
                      <Icon name={c.status === "open" ? "alert" : "check"} size={10} />
                      {c.status === "open" ? "Open" : c.status === "accepted" ? "Accepted" : "Resolved"}
                    </span>
                    <button className="btn btn--ghost btn--sm" style={{ height: 24, padding: "0 10px", fontSize: 11 }} onClick={() => setReply({ ...reply, [c.id]: reply[c.id] == null ? "" : null })}>
                      Reply
                    </button>
                    {c.status === "open" && c.role === "customer" && (
                      <button
                        className="btn btn--ghost btn--sm"
                        style={{ height: 24, padding: "0 10px", fontSize: 11, color: "#1e7849" }}
                        onClick={() => onResolveComment && onResolveComment(c.id, true)}
                      >
                        Mark resolved
                      </button>
                    )}
                    {c.status !== "open" && c.role === "customer" && (
                      <button
                        className="btn btn--ghost btn--sm"
                        style={{ height: 24, padding: "0 10px", fontSize: 11, color: "var(--dark-grey)" }}
                        onClick={() => onResolveComment && onResolveComment(c.id, false)}
                      >
                        Reopen
                      </button>
                    )}
                  </div>
                  {reply[c.id] != null && (
                    <div className="composer" style={{ marginTop: 10, background: "var(--alice-grey)" }}>
                      <textarea placeholder="Reply to this comment…" value={reply[c.id]} onChange={(e) => setReply({ ...reply, [c.id]: e.target.value })} />
                      <div className="composer__actions">
                        <span className="composer__anchor">Replying as <strong>{deal.ae}</strong> (Nami)</span>
                        <button className="btn btn--alloy btn--sm" style={{ height: 28, padding: "0 12px", fontSize: 12 }} disabled={!reply[c.id]?.trim()}>
                          Post reply
                        </button>
                      </div>
                    </div>
                  )}
                </div>
              ))}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

const ACTIVITY_ICONS = {
  created: "plus",
  edited: "edit",
  submitted_for_legal: "warn",
  legal_approved: "checkCircle",
  legal_rejected: "x",
  sent_for_review: "send",
  sent_to_docusign: "send",
  signed: "checkCircle",
  review_revoked: "x",
};
const ACTIVITY_TITLES = {
  submitted_for_legal: "Submitted for legal review",
  legal_approved: "Legal approved",
  legal_rejected: "Legal rejected — back to draft",
  sent_for_review: "Sent to customer for review",
  sent_to_docusign: "Sent to DocuSign",
  signed: "Customer signed",
  review_revoked: "Review link revoked",
};

const ActivityTab = ({ deal }) => {
  const events = deal.activity || [
    { date: "May 8, 2026 · 2:14 PM", actor: "Sarah K.", event: "created" },
    { date: deal.updated, actor: "Sarah K.", event: "edited" },
  ];
  return (
    <div className="card">
      <div className="activity">
        {events.map((e, i) => {
          const title = ACTIVITY_TITLES[e.event] || e.event || "Activity";
          const icon = ACTIVITY_ICONS[e.event] || (i === 0 ? "plus" : "edit");
          const isLegal = e.event === "legal_approved" || e.event === "legal_rejected" || e.event === "submitted_for_legal";
          return (
            <div className="activity-item" key={e.id || i}>
              <div
                className="activity-item__dot"
                style={isLegal ? { background: "rgba(255,193,7,0.20)", color: "#8a5d00" } : undefined}
              >
                <Icon name={icon} size={13} />
              </div>
              <div className="activity-item__body">
                <div className="activity-item__title">{title}</div>
                <div className="activity-item__meta">
                  {e.actor}
                  {e.role && e.role !== "ae" && (
                    <span className={`role-chip role-chip--${e.role}`} style={{ marginLeft: 8, height: 18, fontSize: 9, padding: "0 7px" }}>
                      {ROLE_LABEL_DD[e.role] || e.role}
                    </span>
                  )}
                  {" · "}{e.date}
                </div>
                {e.note && (
                  <div style={{ marginTop: 6, fontSize: 12.5, color: "var(--dark-grey)", lineHeight: 1.5, padding: "8px 12px", background: "var(--alice-grey)", borderRadius: 6 }}>
                    {e.note}
                  </div>
                )}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
};

// ============================================================
// In-review sidebar card — link preview + revoke action
// ============================================================
const InReviewCard = ({ deal, openCount, onViewAsCustomer, onRevokeReviewLink }) => {
  const [confirming, setConfirming] = React.useState(false);
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState(null);

  const revoke = async () => {
    setBusy(true);
    setErr(null);
    try {
      await onRevokeReviewLink();
    } catch (e) {
      setErr(String(e?.message || e));
    } finally {
      setBusy(false);
      setConfirming(false);
    }
  };

  return (
    <div className="card card--tight mb-4" style={{ background: "rgba(21,159,222,0.05)", borderColor: "rgba(21,159,222,0.3)" }}>
      <div style={{ fontSize: 11, fontWeight: 700, color: "#0e6f9c", textTransform: "uppercase", letterSpacing: "0.06em", marginBottom: 6 }}>In customer review</div>
      <div style={{ fontSize: 13.5, color: "var(--navy)", fontWeight: 600, marginBottom: 4 }}>
        {openCount > 0 ? `${openCount} open comment${openCount === 1 ? "" : "s"}` : "Awaiting customer feedback"}
      </div>
      <div style={{ fontSize: 12, color: "var(--dark-grey)", lineHeight: 1.5 }}>
        Review link sent {deal.reviewSentAt} to <strong>{deal.reviewSentTo}</strong>.
      </div>
      <div style={{ marginTop: 8, fontSize: 11.5, color: "var(--dark-grey)", lineHeight: 1.5 }}>
        Customer can edit their details (signatory, addresses, billing contact) directly in the draft.
        Edits flow into the DocuSign envelope when they trigger signature.
      </div>
      <div style={{ marginTop: 10, fontSize: 11.5, fontFamily: "ui-monospace, Menlo, monospace", color: "var(--blue-alloy)", padding: "6px 8px", background: "#fff", borderRadius: 6, border: "1px solid var(--strokes)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
        {deal.reviewLink}
      </div>
      <button className="btn btn--ghost btn--sm" style={{ marginTop: 10, width: "100%" }} onClick={onViewAsCustomer}>
        <Icon name="eye" size={13} /> Open as customer
      </button>

      {!confirming ? (
        <button
          className="btn btn--ghost btn--sm"
          style={{ marginTop: 6, width: "100%", color: "var(--accent-red)" }}
          onClick={() => { setErr(null); setConfirming(true); }}
        >
          <Icon name="x" size={13} /> Revoke review link
        </button>
      ) : (
        <div style={{ marginTop: 10, padding: 10, background: "#fff", border: "1px solid rgba(255,91,116,0.4)", borderRadius: 8 }}>
          <div style={{ fontSize: 12.5, color: "var(--navy)", fontWeight: 600, marginBottom: 4 }}>
            Revoke this link?
          </div>
          <div style={{ fontSize: 11.5, color: "var(--dark-grey)", lineHeight: 1.5, marginBottom: 8 }}>
            {deal.customer} won't be able to open it anymore — even if they're mid-review. The deal goes back to draft.
          </div>
          <div style={{ display: "flex", gap: 6 }}>
            <button
              className="btn btn--ghost btn--sm"
              style={{ flex: 1 }}
              disabled={busy}
              onClick={() => setConfirming(false)}
            >Cancel</button>
            <button
              className="btn btn--alloy btn--sm"
              style={{ flex: 1, background: "var(--accent-red)" }}
              disabled={busy}
              onClick={revoke}
            >{busy ? "Revoking…" : "Revoke link"}</button>
          </div>
          {err && (
            <div style={{ marginTop: 8, fontSize: 11.5, color: "#b3273f" }}>{err}</div>
          )}
        </div>
      )}
    </div>
  );
};

// ============================================================
// Deal Desk exceptions tab — managers approve/reject AE requests
// ============================================================
const RULE_TITLES = (() => {
  // Lookup table built from the validator's rule list. We don't want the
  // tab to depend on the validator running on the current deal — it has
  // to show resolved exceptions even after the underlying rule starts
  // passing.
  const map = {};
  (window.NAMI_VALIDATE?.RULES || []).forEach((r) => { map[r.id] = r.title; });
  return map;
})();

const ExceptionsTab = ({ deal, user, isDealDeskReviewer, exceptions, onResolveException, onRequestException }) => {
  const [composer, setComposer] = React.useState(null);   // exceptionId
  const [mode, setMode] = React.useState("approve");       // approve | reject
  const [note, setNote] = React.useState("");
  const [busy, setBusy] = React.useState(false);

  const pending  = exceptions.filter((e) => e.status === "requested");
  const approved = exceptions.filter((e) => e.status === "approved");
  const rejected = exceptions.filter((e) => e.status === "rejected");

  const handleResolve = async (exceptionId, decision) => {
    if (decision === "rejected" && !note.trim()) return;
    setBusy(true);
    try {
      await onResolveException(exceptionId, decision, note.trim());
      setComposer(null);
      setNote("");
    } finally { setBusy(false); }
  };

  const renderRow = (ex) => (
    <div
      key={ex.id}
      className={`exception-row exception-row--${ex.status}`}
    >
      <div className="exception-row__head">
        <div style={{ flex: 1, minWidth: 0 }}>
          <div className="exception-row__rule">{RULE_TITLES[ex.ruleId] || ex.ruleId}</div>
          <div className="exception-row__meta">
            Requested by <strong>{ex.requestedBy}</strong>
            {ex.requestedAt && <> · {formatTime(ex.requestedAt)}</>}
          </div>
        </div>
        <span className={`exception-row__status exception-row__status--${ex.status}`}>
          {ex.status === "requested" ? "Pending" :
           ex.status === "approved" ? "Approved" : "Rejected"}
        </span>
      </div>

      {ex.justification && (
        <div className="exception-row__just">
          <Icon name="info" size={12} /> {ex.justification}
        </div>
      )}

      {ex.status !== "requested" && (
        <div className="exception-row__resolution">
          {ex.status === "approved" ? "Approved" : "Rejected"} by <strong>{ex.resolvedBy || "—"}</strong>
          {ex.resolvedAt && <> · {formatTime(ex.resolvedAt)}</>}
          {ex.resolutionNote && <div style={{ marginTop: 4 }}>{ex.resolutionNote}</div>}
        </div>
      )}

      {isDealDeskReviewer && ex.status === "requested" && (
        composer === ex.id ? (
          <div className="exception-composer" style={{ marginTop: 10 }}>
            <textarea
              placeholder={mode === "approve" ? "Optional note (visible to AE)" : "Why is this rejected? (required)"}
              value={note}
              onChange={(e) => setNote(e.target.value)}
              autoFocus
            />
            <div className="exception-composer__row">
              <button
                className="btn btn--ghost btn--sm"
                disabled={busy}
                onClick={() => { setComposer(null); setNote(""); }}
              >Cancel</button>
              <button
                className={`btn btn--alloy btn--sm`}
                style={mode === "reject" ? { background: "var(--accent-red)" } : undefined}
                disabled={busy || (mode === "reject" && !note.trim())}
                onClick={() => handleResolve(ex.id, mode === "approve" ? "approved" : "rejected")}
              >
                {busy ? "Saving…" : mode === "approve" ? "Approve" : "Reject"}
              </button>
            </div>
          </div>
        ) : (
          <div className="exception-row__actions">
            <button
              className="btn btn--outline btn--sm"
              style={{ color: "var(--accent-red)", borderColor: "rgba(255,91,116,0.5)" }}
              onClick={() => { setComposer(ex.id); setMode("reject"); setNote(""); }}
            >
              <Icon name="x" size={12} /> Reject
            </button>
            <button
              className="btn btn--alloy btn--sm"
              onClick={() => { setComposer(ex.id); setMode("approve"); setNote(""); }}
            >
              <Icon name="check" size={12} /> Approve
            </button>
          </div>
        )
      )}
    </div>
  );

  return (
    <div className="flex-col gap-3">
      <div className="card" style={{ padding: 0, overflow: "hidden" }}>
        <div style={{ padding: "14px 20px", borderBottom: "1px solid var(--strokes)", display: "flex", justifyContent: "space-between", alignItems: "center" }}>
          <div style={{ fontSize: 13, fontWeight: 700, color: "var(--navy)", letterSpacing: "-0.01em" }}>
            Deal Desk exceptions
          </div>
          <span style={{ fontSize: 11.5, color: "var(--dark-grey)" }}>
            {pending.length} pending · {approved.length} approved · {rejected.length} rejected
          </span>
        </div>

        {exceptions.length === 0 && (
          <div style={{ padding: 40, textAlign: "center", color: "var(--dark-grey)", fontSize: 13 }}>
            <Icon name="checkCircle" size={28} color="var(--strokes)" />
            <div style={{ marginTop: 12, fontWeight: 600, color: "var(--navy)" }}>No exceptions on this deal</div>
            <div style={{ marginTop: 4 }}>
              When a deal fails a Deal Desk rule, the AE can request an exception from step 6 of the wizard.
            </div>
          </div>
        )}

        {pending.length > 0 && (
          <div className="flex-col" style={{ padding: 16, gap: 12 }}>
            {pending.map(renderRow)}
          </div>
        )}

        {(approved.length > 0 || rejected.length > 0) && (
          <details style={{ borderTop: "1px solid var(--strokes)", padding: 16 }}>
            <summary style={{ cursor: "pointer", fontSize: 12, fontWeight: 700, color: "var(--dark-grey)", letterSpacing: "-0.01em" }}>
              History ({approved.length + rejected.length})
            </summary>
            <div className="flex-col" style={{ marginTop: 12, gap: 12 }}>
              {[...approved, ...rejected].map(renderRow)}
            </div>
          </details>
        )}
      </div>
    </div>
  );
};

// ============================================================
// Legal review tab — internal Nami workflow
// ============================================================
const LegalReviewTab = ({ deal, user, isLegalReviewer, flags, onApprove, onReject, onPostComment }) => {
  const [note, setNote] = React.useState("");
  const [rejectMode, setRejectMode] = React.useState(false);
  const isPending = deal.status === "legal";
  const internal = deal.internalComments || [];

  return (
    <div className="flex-col gap-3">
      {/* Flag summary */}
      <div className="card" style={{ padding: 0, overflow: "hidden" }}>
        <div style={{ padding: "14px 20px", borderBottom: "1px solid var(--strokes)", display: "flex", alignItems: "center", justifyContent: "space-between" }}>
          <div style={{ fontSize: 13, fontWeight: 700, color: "var(--navy)", letterSpacing: "-0.01em" }}>
            Variants flagged for counsel
          </div>
          <span style={{ fontSize: 11.5, color: "var(--dark-grey)" }}>
            {flags.length} flagged · {deal.legalSubmittedAt ? `submitted ${deal.legalSubmittedAt}` : "not yet submitted"}
          </span>
        </div>
        {flags.length === 0 ? (
          <div style={{ padding: 32, textAlign: "center", color: "var(--dark-grey)" }}>
            <Icon name="checkCircle" size={24} color="var(--kelp)" />
            <div style={{ marginTop: 10, fontWeight: 600, color: "var(--navy)" }}>No variants need counsel sign-off</div>
            <div style={{ marginTop: 4, fontSize: 12.5 }}>Everything selected is within the pre-approved menu.</div>
          </div>
        ) : (
          <div className="flex-col" style={{ padding: 20, gap: 12 }}>
            {flags.map((f) => (
              <div key={f.variantId} style={{ padding: 14, border: "1px solid rgba(255,193,7,0.45)", background: "rgba(255,193,7,0.06)", borderRadius: 10 }}>
                <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 12 }}>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 13.5, fontWeight: 700, color: "var(--navy)" }}>{f.category}</div>
                    <div style={{ fontSize: 11, color: "var(--dark-grey)", textTransform: "uppercase", letterSpacing: "0.06em", marginTop: 2 }}>{f.section}</div>
                  </div>
                  <span style={{ fontSize: 11, padding: "3px 9px", borderRadius: 9999, background: "#fff", border: "1px solid rgba(255,193,7,0.5)", color: "#8a5d00", fontWeight: 700 }}>
                    {f.chosen}
                  </span>
                </div>
                <div style={{ marginTop: 8, fontSize: 12.5, color: "var(--dark-grey)", lineHeight: 1.5 }}>
                  {f.reason}
                </div>
              </div>
            ))}
          </div>
        )}
      </div>

      {/* Internal thread */}
      <InternalThread
        deal={deal}
        user={user}
        comments={internal}
        onPostComment={onPostComment}
      />

      {/* Decision panel — only legal/admin can act, and only when pending */}
      {isLegalReviewer && isPending && (
        <div className="card" style={{ padding: 16, background: "var(--alice-grey)" }}>
          <div style={{ fontSize: 12, fontWeight: 700, color: "var(--navy)", letterSpacing: "-0.01em", marginBottom: 10 }}>
            Decision
          </div>
          {!rejectMode ? (
            <div style={{ display: "flex", gap: 8 }}>
              <button
                className="btn btn--alloy btn--sm"
                style={{ flex: 1 }}
                onClick={() => { onApprove(note.trim() || null); setNote(""); }}
              >
                <Icon name="checkCircle" size={13} /> Approve and clear
              </button>
              <button
                className="btn btn--outline btn--sm"
                style={{ flex: 1, color: "var(--accent-red)", borderColor: "rgba(255,91,116,0.5)" }}
                onClick={() => setRejectMode(true)}
              >
                <Icon name="x" size={13} /> Reject back to AE
              </button>
            </div>
          ) : (
            <div className="flex-col gap-2">
              <textarea
                placeholder="What does the AE need to change before this can ship? (Required)"
                value={note}
                onChange={(e) => setNote(e.target.value)}
                style={{ width: "100%", minHeight: 90, padding: "10px 12px", border: "1px solid var(--strokes)", borderRadius: 6, fontSize: 13.5, fontFamily: "inherit", color: "var(--navy)", resize: "vertical" }}
              />
              <div style={{ display: "flex", gap: 8 }}>
                <button className="btn btn--ghost btn--sm" onClick={() => { setRejectMode(false); setNote(""); }}>
                  Cancel
                </button>
                <button
                  className="btn btn--alloy btn--sm"
                  style={{ flex: 1, background: "var(--accent-red)" }}
                  disabled={!note.trim()}
                  onClick={() => { onReject(note.trim()); setNote(""); setRejectMode(false); }}
                >
                  Send rejection back to {deal.ae}
                </button>
              </div>
            </div>
          )}
        </div>
      )}

      {!isLegalReviewer && isPending && (
        <div className="card" style={{ padding: 16, fontSize: 13, color: "var(--dark-grey)", textAlign: "center" }}>
          Counsel is reviewing. You'll get an internal notification when there's an update.
        </div>
      )}

      {deal.legalRejectionNote && deal.status === "draft" && (
        <div className="card" style={{ padding: 16, borderColor: "rgba(255,91,116,0.4)", background: "rgba(255,91,116,0.05)" }}>
          <div style={{ fontSize: 11, fontWeight: 700, color: "#b3273f", textTransform: "uppercase", letterSpacing: "0.06em", marginBottom: 6 }}>
            Last rejection
          </div>
          <div style={{ fontSize: 13, color: "var(--navy)", lineHeight: 1.5 }}>{deal.legalRejectionNote}</div>
          <div style={{ marginTop: 6, fontSize: 11.5, color: "var(--dark-grey)" }}>
            By {deal.legalRejectedBy} · {deal.legalRejectedAt}
          </div>
        </div>
      )}
    </div>
  );
};

// ============================================================
// Internal Nami-only comment thread (shared by legal review + future surfaces)
// ============================================================
// Detect an in-progress @-mention immediately before the textarea's caret.
// Returns the start index of the "@" and the partial query the user has
// typed since, or null if there's no live mention. Stops at whitespace so
// "@Sarah Kim" only stays "live" through "Sarah" — once they hit space
// after picking, the autocomplete dismisses.
const findActiveMention = (text, caret) => {
  if (caret == null || caret < 0) return null;
  const upToCaret = text.slice(0, caret);
  const at = upToCaret.lastIndexOf("@");
  if (at < 0) return null;
  // "@" must follow start-of-text or a whitespace char, else it's mid-word.
  if (at > 0 && !/\s/.test(upToCaret[at - 1])) return null;
  const query = upToCaret.slice(at + 1);
  if (/\s/.test(query)) return null;
  return { start: at, query };
};

// Render a comment body with @-mentions styled. We match `@<name>` where
// name is a known teammate; anything else stays plain text.
const renderBodyWithMentions = (body, teammates) => {
  if (!body) return null;
  const names = teammates.map((t) => t.name).sort((a, b) => b.length - a.length);
  if (!names.length) return body;
  // Build a regex that matches @<name> for any known teammate.
  const escaped = names.map((n) => n.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
  const re = new RegExp(`@(${escaped.join("|")})`, "g");
  const out = [];
  let last = 0;
  let m;
  while ((m = re.exec(body)) !== null) {
    if (m.index > last) out.push(body.slice(last, m.index));
    out.push(
      <span key={`m-${m.index}`} className="mention">@{m[1]}</span>,
    );
    last = m.index + m[0].length;
  }
  if (last < body.length) out.push(body.slice(last));
  return out;
};

const InternalThread = ({ deal, user, comments, onPostComment }) => {
  const teammates = window.NAMI_DATA.TEAMMATES || [];
  const [draft, setDraft] = React.useState("");
  const [caret, setCaret] = React.useState(0);
  const [activeIdx, setActiveIdx] = React.useState(0);
  const textareaRef = React.useRef(null);

  const mention = findActiveMention(draft, caret);
  const filteredTeammates = mention
    ? teammates.filter((t) => {
        const q = mention.query.toLowerCase();
        return !q || t.name.toLowerCase().includes(q) || t.email.toLowerCase().includes(q);
      })
    : [];

  React.useEffect(() => {
    // Reset highlight when the suggestion list changes shape.
    setActiveIdx(0);
  }, [mention?.query, filteredTeammates.length]);

  const insertMention = (teammate) => {
    if (!mention) return;
    const before = draft.slice(0, mention.start);
    const after = draft.slice(caret);
    const inserted = `@${teammate.name} `;
    const next = `${before}${inserted}${after}`;
    setDraft(next);
    const nextCaret = before.length + inserted.length;
    // Defer caret restore so the textarea picks up the new value first.
    setTimeout(() => {
      if (textareaRef.current) {
        textareaRef.current.focus();
        textareaRef.current.setSelectionRange(nextCaret, nextCaret);
        setCaret(nextCaret);
      }
    }, 0);
  };

  const post = () => {
    if (!draft.trim()) return;
    onPostComment(draft);
    setDraft("");
    setCaret(0);
  };

  const handleKeyDown = (e) => {
    if (filteredTeammates.length > 0) {
      if (e.key === "ArrowDown") {
        e.preventDefault();
        setActiveIdx((i) => (i + 1) % filteredTeammates.length);
        return;
      }
      if (e.key === "ArrowUp") {
        e.preventDefault();
        setActiveIdx((i) => (i - 1 + filteredTeammates.length) % filteredTeammates.length);
        return;
      }
      if (e.key === "Enter" || e.key === "Tab") {
        e.preventDefault();
        insertMention(filteredTeammates[activeIdx]);
        return;
      }
      if (e.key === "Escape") {
        e.preventDefault();
        // Move caret past the @ so the autocomplete dismisses.
        const next = draft.slice(0, mention.start) + draft.slice(caret);
        setDraft(next);
        setCaret(mention.start);
        return;
      }
    }
    if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) post();
  };

  const updateCaret = (e) => setCaret(e.target.selectionStart);

  return (
    <div className="card" style={{ padding: 0, overflow: "hidden" }}>
      <div style={{ padding: "14px 20px", borderBottom: "1px solid var(--strokes)", display: "flex", alignItems: "center", justifyContent: "space-between" }}>
        <div style={{ fontSize: 13, fontWeight: 700, color: "var(--navy)", letterSpacing: "-0.01em" }}>
          Internal thread
        </div>
        <span style={{ fontSize: 11, color: "var(--dark-grey)" }}>
          <Icon name="lock" size={11} /> Visible to Nami only
        </span>
      </div>

      {comments.length === 0 && (
        <div style={{ padding: 28, textAlign: "center", color: "var(--dark-grey)", fontSize: 13 }}>
          No internal comments yet. Use this thread to coordinate with counsel — it doesn't get bundled into the customer PDF.
          <div style={{ marginTop: 8, fontSize: 12 }}>Type <code>@</code> to ping a teammate.</div>
        </div>
      )}

      {comments.length > 0 && (
        <div className="flex-col" style={{ padding: 16, gap: 10 }}>
          {comments.map((c) => (
            <div key={c.id} className="comment is-internal" style={{ background: "var(--alice-grey)", border: "1px solid var(--strokes)" }}>
              <div className="comment__head">
                <div
                  className="comment__avatar"
                  style={{ background: c.role === "legal" ? "rgba(255,193,7,0.35)" : c.role === "admin" ? "var(--navy)" : "var(--blue-alloy)", color: c.role === "legal" ? "#5a3800" : "#fff" }}
                >
                  {(c.author || "?").split(" ").map((n) => n[0]).slice(0, 2).join("")}
                </div>
                <div className="comment__author">{c.author}</div>
                {c.role && (
                  <span className={`role-chip role-chip--${c.role}`} style={{ height: 18, fontSize: 9, padding: "0 7px" }}>
                    {ROLE_LABEL_DD[c.role] || c.role}
                  </span>
                )}
                <div className="comment__time">{formatTime(c.time)}</div>
              </div>
              <div className="comment__body">{renderBodyWithMentions(c.body, teammates)}</div>
            </div>
          ))}
        </div>
      )}

      <div className="composer-wrap" style={{ borderTop: "1px solid var(--strokes)", padding: 14, background: "var(--alice-grey)" }}>
        <textarea
          ref={textareaRef}
          placeholder={`Comment as ${user?.name || "you"}… (type @ to mention)`}
          value={draft}
          onChange={(e) => { setDraft(e.target.value); setCaret(e.target.selectionStart); }}
          onKeyDown={handleKeyDown}
          onKeyUp={updateCaret}
          onClick={updateCaret}
          onSelect={updateCaret}
          style={{ width: "100%", minHeight: 64, padding: "10px 12px", border: "1px solid var(--strokes)", borderRadius: 6, fontSize: 13.5, fontFamily: "inherit", color: "var(--navy)", background: "#fff", resize: "vertical" }}
        />

        {filteredTeammates.length > 0 && (
          <div className="mention-menu">
            {filteredTeammates.slice(0, 6).map((t, i) => (
              <button
                key={t.email}
                className={`mention-menu__item ${i === activeIdx ? "is-active" : ""}`}
                onMouseDown={(e) => { e.preventDefault(); insertMention(t); }}
                onMouseEnter={() => setActiveIdx(i)}
                type="button"
              >
                <span className="mention-menu__name">{t.name}</span>
                <span className={`role-chip role-chip--${t.role}`} style={{ height: 16, fontSize: 9, padding: "0 6px" }}>
                  {ROLE_LABEL_DD[t.role] || t.role}
                </span>
                <span className="mention-menu__email">{t.email}</span>
              </button>
            ))}
          </div>
        )}

        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: 8 }}>
          <span style={{ fontSize: 11, color: "var(--dark-grey)" }}>
            ⌘+Enter to post · @ to mention · Internal only
          </span>
          <button className="btn btn--alloy btn--sm" disabled={!draft.trim()} onClick={post}>
            Post comment
          </button>
        </div>
      </div>
    </div>
  );
};

const formatTime = (iso) => {
  if (!iso) return "";
  try {
    const d = new Date(iso);
    if (isNaN(d.getTime())) return iso;
    return d.toLocaleString("en-US", {
      month: "short", day: "numeric",
      hour: "numeric", minute: "2-digit",
    });
  } catch { return iso; }
};

// ============================================================
// Customer-proposed changes card — surfaces edits the customer made on
// their review link so the AE can apply or discard before re-sending.
// ============================================================
const EDIT_FIELDS = [
  { key: "customerLegal",   label: "Legal entity",      kind: "scalar" },
  { key: "customerAddress", label: "Customer address",  kind: "scalar" },
  { key: "noticeAddress",   label: "Legal Notices",     kind: "scalar" },
  { key: "contractAdmin",   label: "Signatory",         kind: "nested",
    subFields: [
      { key: "name",  label: "Name"  },
      { key: "title", label: "Title" },
      { key: "email", label: "Email" },
    ],
  },
  { key: "billingContact",  label: "A/P email address", kind: "nested",
    subFields: [
      { key: "email", label: "A/P email" },
    ],
  },
];

const CustomerEditsCard = ({ deal, edits, editedAt, onApply, onDiscard }) => {
  const [confirming, setConfirming] = React.useState(null); // "apply" | "discard" | null
  const [busy, setBusy] = React.useState(false);

  // Build the diff list: only fields where the customer actually
  // proposed a different value than what's on the deal.
  const rows = [];
  for (const f of EDIT_FIELDS) {
    const proposed = edits[f.key];
    if (proposed == null) continue;
    if (f.kind === "scalar") {
      const current = deal[f.key] || "";
      if ((proposed || "") === current) continue;
      rows.push({ label: f.label, current: current || "—", proposed: proposed || "—" });
    } else {
      // nested — emit a row per changed sub-field
      const currentParent = deal[f.key] || {};
      for (const sub of f.subFields) {
        if (!(sub.key in proposed)) continue;
        const cur = currentParent[sub.key] || "";
        const prop = proposed[sub.key] || "";
        if (cur === prop) continue;
        rows.push({
          label: `${f.label} — ${sub.label}`,
          current: cur || "—",
          proposed: prop || "—",
        });
      }
    }
  }

  if (!rows.length) return null;

  const run = async (which) => {
    setBusy(true);
    try {
      if (which === "apply") await onApply();
      else await onDiscard();
    } finally {
      setBusy(false);
      setConfirming(null);
    }
  };

  return (
    <div className="card card--tight mb-4" style={{ background: "rgba(11,74,142,0.04)", borderColor: "rgba(11,74,142,0.30)" }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 6 }}>
        <div style={{ fontSize: 11, fontWeight: 700, color: "var(--blue-alloy)", textTransform: "uppercase", letterSpacing: "0.06em" }}>
          Customer-proposed changes
        </div>
        <span style={{ fontSize: 10, padding: "1px 7px", borderRadius: 9999, background: "rgba(11,74,142,0.18)", color: "var(--blue-alloy)", fontWeight: 700 }}>
          {rows.length}
        </span>
      </div>
      <div style={{ fontSize: 12.5, color: "var(--navy)", lineHeight: 1.5, marginBottom: 10 }}>
        {deal.customer} edited details from their review link.
        {editedAt && <span style={{ color: "var(--dark-grey)" }}> {formatTime(new Date(editedAt).toISOString())}.</span>}
      </div>

      <div className="flex-col" style={{ gap: 8, marginBottom: 12 }}>
        {rows.map((r, i) => (
          <div key={i} style={{ background: "#fff", border: "1px solid var(--strokes)", borderRadius: 8, padding: "8px 10px" }}>
            <div style={{ fontSize: 10.5, fontWeight: 700, color: "var(--dark-grey)", textTransform: "uppercase", letterSpacing: "0.05em", marginBottom: 4 }}>
              {r.label}
            </div>
            <div style={{ fontSize: 11.5, color: "var(--dark-grey)", display: "flex", gap: 6, alignItems: "baseline" }}>
              <span style={{ flex: "0 0 auto" }}>From:</span>
              <span style={{ color: "var(--navy)", textDecoration: "line-through", flex: 1, wordBreak: "break-word" }}>{r.current}</span>
            </div>
            <div style={{ fontSize: 11.5, color: "var(--dark-grey)", display: "flex", gap: 6, alignItems: "baseline", marginTop: 2 }}>
              <span style={{ flex: "0 0 auto" }}>To:</span>
              <span style={{ color: "var(--blue-alloy)", fontWeight: 600, flex: 1, wordBreak: "break-word" }}>{r.proposed}</span>
            </div>
          </div>
        ))}
      </div>

      {confirming == null ? (
        <div style={{ display: "flex", gap: 6 }}>
          <button
            className="btn btn--outline btn--sm"
            style={{ flex: 1, color: "var(--accent-red)", borderColor: "rgba(255,91,116,0.5)" }}
            onClick={() => setConfirming("discard")}
          >
            <Icon name="x" size={12} /> Discard
          </button>
          <button
            className="btn btn--alloy btn--sm"
            style={{ flex: 1 }}
            onClick={() => setConfirming("apply")}
          >
            <Icon name="check" size={12} /> Apply all
          </button>
        </div>
      ) : (
        <div style={{ padding: 10, background: "#fff", border: "1px solid var(--strokes)", borderRadius: 8 }}>
          <div style={{ fontSize: 12, color: "var(--navy)", fontWeight: 600, marginBottom: 8 }}>
            {confirming === "apply"
              ? `Apply ${rows.length} change${rows.length === 1 ? "" : "s"} to the deal record?`
              : "Discard customer's proposed changes? They won't carry into the next draft."}
          </div>
          <div style={{ display: "flex", gap: 6 }}>
            <button className="btn btn--ghost btn--sm" style={{ flex: 1 }} disabled={busy} onClick={() => setConfirming(null)}>
              Cancel
            </button>
            <button
              className="btn btn--alloy btn--sm"
              style={{ flex: 1, background: confirming === "discard" ? "var(--accent-red)" : undefined }}
              disabled={busy}
              onClick={() => run(confirming)}
            >
              {busy ? "Working…" : confirming === "apply" ? "Apply" : "Discard"}
            </button>
          </div>
        </div>
      )}
    </div>
  );
};

window.DealDetail = DealDetail;
