// window.ExceptionDetailPanel — a focused, context-rich review overlay for a
// single exception, opened via window.openExceptionDetail(exception).
//
// WHY THIS EXISTS. Clicking "Review →" on an exception used to call
// PerduraSynthesis.navigateDrill(drill_into, …), which resolves a routing TOKEN
// ("spend_by_vendor") to a whole-page destination (Data Room, Expenses) and
// jumps there — discarding the exception's headline, driver and recommended
// action and dropping the user on a cold raw table. This panel keeps the
// narrative on screen and turns that jump into a deliberate, labelled step.
//
// ─── DATA REALITY (read before changing anything) ────────────────────────────
//
// FIELD NAMES. An exception item (from cfo-synthesis surface_type
// "exceptions_inbox", see src/pages-exceptions-inbox.jsx) carries:
//   headline, supporting_detail, diagnosed_driver, recommended_action,
//   estimated_dollar_impact, severity (critical|high|medium|low|info),
//   period_end, drill_into, signal_id, source_signal_ids.
// It does NOT carry detail / driver / recommendation / amount / priorAmount /
// account_code / vendor / category / account. We read the real names and fall
// back to those aliases only so a differently-shaped caller can't crash us.
//
// NO CLIENT-SIDE TRANSACTION SCOPE. drill_into is a PAGE token, not a set of GL
// codes; the signal's account/vendor evidence is not surfaced to the client;
// and gl_transactions has no vendor/contact/description column (see
// drill-panel.jsx). So we CANNOT honestly list "the transactions causing it"
// from the exception object — any client-side match would be fabricated. The
// transactions live behind the drill_into target page, already correctly
// scoped there, so we route to it with a clear label instead of inventing a
// table. Do not add a transactions grid keyed on vendor/description here.
//
// ESCALATION. "See the underlying detail" calls the SAME
// PerduraSynthesis.navigateDrill used everywhere else, now passing setDrillKey
// (the briefing path previously omitted it, under-scoping the Data Room). This
// panel is an on-ramp to the existing drill, not a second drill overlay.

(function () {
  const h = React.createElement;

  const C = {
    navy: "#0d2040", card: "#fff", border: "#E4E8F0",
    text1: "#1A2233", text2: "#475569", muted: "#6B7A99",
    accent: "#1C4ED8", accentSoft: "#EEF2FF",
    green: "#059669", greenSoft: "#DCFCE7", greenBorder: "#A7F3D0",
  };

  const money = (v) => (window.PerduraFormat && window.PerduraFormat.money)
    ? window.PerduraFormat.money(Math.abs(Number(v) || 0), { compact: false })
    : "$" + Math.abs(Math.round(Number(v) || 0)).toLocaleString();

  // Severity → presentation. Real values: critical | high | medium | low | info.
  const SEV = {
    critical: { color: "#b91c1c", bg: "#fee2e2", icon: "🔴", label: "Critical" },
    high:     { color: "#dc2626", bg: "#fee2e2", icon: "🔴", label: "High priority" },
    medium:   { color: "#b45309", bg: "#fef3c7", icon: "🟡", label: "Medium priority" },
    low:      { color: "#047857", bg: "#d1fae5", icon: "🟢", label: "Low priority" },
    info:     { color: "#1C4ED8", bg: "#EEF2FF", icon: "🔵", label: "For your awareness" },
  };
  const sevOf = (s) => SEV[String(s || "info").toLowerCase()] || SEV.info;

  // Human names for the drill destinations PerduraSynthesis.resolveDrill maps a
  // drill_into token to (page keys mirror synthesis-client.js DRILL_ROUTES).
  const PAGE_LABEL = {
    arap: "AR / AP Aging", data_room: "the Data Room", cash: "Cash Flow & Runway",
    cash_flow_statement: "the Cash Flow Statement", expenses: "Expenses",
    customer: "Customer analysis", margin: "Margin Analysis",
    income_statement: "the Income Statement", balance_sheet: "the Balance Sheet",
    reconciliation: "Reconciliation",
  };

  function resolveDestination(drillInto) {
    if (!drillInto) return null;
    const S = window.PerduraSynthesis;
    if (!S || !S.resolveDrill) return null;
    const r = S.resolveDrill(drillInto) || {};
    return { page: r.page, drillKey: r.drillKey || null, label: PAGE_LABEL[r.page] || "the detail view" };
  }

  const fmtAsOf = (iso) => {
    if (!iso) return null;
    const d = new Date(iso);
    return isNaN(d.getTime()) ? null : d.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
  };

  // ── Panel ──────────────────────────────────────────────────────────────────
  // Props: { exception, onClose, onResolve?, setPage?, setDrillKey?, goToInbox? }
  function ExceptionDetailPanel(props) {
    const ex = props && props.exception;
    if (!ex) return null;

    // Real field first, spec-alias fallback second — never invent a value.
    const headline    = ex.headline || ex.name || "Exception";
    const why         = ex.supporting_detail || ex.detail || null;
    const driver      = ex.diagnosed_driver || ex.driver || null;
    const action      = ex.recommended_action || ex.recommendation || null;
    const impact      = (ex.estimated_dollar_impact != null) ? ex.estimated_dollar_impact
                        : (ex.amount != null ? ex.amount : null);
    const asOf        = fmtAsOf(ex.period_end || ex.as_of || null);
    const sev         = sevOf(ex.severity);
    const dest        = resolveDestination(ex.drill_into);

    const close = () => props.onClose && props.onClose();

    const setPage = props.setPage || window.__perduraSetPage || null;
    const setDrillKey = props.setDrillKey || null;

    const escalate = () => {
      close();
      if (window.PerduraSynthesis && window.PerduraSynthesis.navigateDrill && ex.drill_into) {
        window.PerduraSynthesis.navigateDrill(ex.drill_into, setPage, setDrillKey);
      } else if (setPage) {
        setPage("exceptions");
      }
    };

    const section = (label, body, opts) => body ? h("div", { style: { marginBottom: 18 } },
      h("div", { style: { fontSize: 11, fontWeight: 700, color: (opts && opts.labelColor) || C.muted, textTransform: "uppercase", letterSpacing: 0.5, marginBottom: 6 } }, label),
      h("div", { style: { fontSize: 13, color: C.text2, lineHeight: 1.65 } }, body)) : null;

    const body = h("div", {
      style: { width: 640, maxWidth: "95vw", height: "100vh", background: C.card, overflowY: "auto", boxShadow: "-8px 0 40px rgba(0,0,0,0.2)", display: "flex", flexDirection: "column" },
      onClick: (e) => e.stopPropagation(),
    },
      // Header
      h("div", { style: { background: C.navy, padding: "22px 26px", flexShrink: 0 } },
        h("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginBottom: 12, gap: 12 } },
          h("div", { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" } },
            h("span", { style: { background: sev.bg, color: sev.color, padding: "3px 10px", borderRadius: 20, fontSize: 11, fontWeight: 700 } }, sev.icon + " " + sev.label),
            asOf ? h("span", { style: { color: "rgba(255,255,255,0.45)", fontSize: 11.5 } }, "as of " + asOf) : null),
          h("button", { onClick: close, "aria-label": "Close", style: { background: "none", border: "none", color: "rgba(255,255,255,0.55)", fontSize: 24, cursor: "pointer", padding: 0, lineHeight: 1 } }, "×")),
        h("div", { style: { fontSize: 18, fontWeight: 800, color: "#fff", lineHeight: 1.4 } }, headline)),

      // Body
      h("div", { style: { padding: "22px 26px", flex: 1 } },
        impact != null ? h("div", { style: { background: "#f8faff", borderRadius: 10, padding: "14px 16px", marginBottom: 18, display: "inline-block", minWidth: 180 } },
          h("div", { style: { fontSize: 11, color: C.muted, fontWeight: 600, textTransform: "uppercase", letterSpacing: 0.4, marginBottom: 4 } }, "Estimated impact"),
          h("div", { style: { fontSize: 24, fontWeight: 800, color: C.navy, fontVariantNumeric: "tabular-nums" } }, money(impact))) : null,

        section("What this is", why),

        driver ? h("div", { style: { background: "#fffbeb", border: "1px solid #fcd34d", borderRadius: 10, padding: "14px 16px", marginBottom: 18 } },
          h("div", { style: { fontSize: 11, fontWeight: 700, color: "#92400e", textTransform: "uppercase", letterSpacing: 0.4, marginBottom: 4 } }, "Root cause"),
          h("div", { style: { fontSize: 13, color: "#78350f", lineHeight: 1.65 } }, driver)) : null,

        action ? h("div", { style: { background: "linear-gradient(135deg,#0d2040 0%,#1a3a5c 100%)", borderRadius: 10, padding: "16px 18px", marginBottom: 18 } },
          h("div", { style: { fontSize: 11, fontWeight: 700, color: "#34d399", textTransform: "uppercase", letterSpacing: 0.4, marginBottom: 6 } }, "→ Recommended action"),
          h("div", { style: { fontSize: 13, color: "#c8d6e8", lineHeight: 1.65 } }, action)) : null,

        // Where the underlying numbers live — honest escalation, not a fabricated grid.
        h("div", { style: { border: "1px solid " + C.border, borderRadius: 10, padding: "14px 16px" } },
          h("div", { style: { fontSize: 11, fontWeight: 700, color: C.muted, textTransform: "uppercase", letterSpacing: 0.4, marginBottom: 6 } }, "The underlying transactions"),
          h("div", { style: { fontSize: 12.5, color: C.text2, lineHeight: 1.6, marginBottom: 12 } },
            dest
              ? ("The transactions behind this exception open in " + dest.label + ", scoped to this signal. We don't reconstruct them here — that view is the source of truth.")
              : "This exception is a period-level signal with no single account behind it, so there is no transaction list to open. The recommended action above is the next step."),
          dest ? h("button", { onClick: escalate,
            style: { padding: "10px 16px", background: C.accentSoft, color: C.accent, border: "1px solid " + C.accent, borderRadius: 8, cursor: "pointer", fontWeight: 700, fontSize: 12.5 } },
            "Open " + dest.label + " →") : null)),

      // Footer
      h("div", { style: { padding: "14px 26px", borderTop: "1px solid #f0f0f0", flexShrink: 0, display: "flex", gap: 8, justifyContent: "space-between", alignItems: "center", background: C.card } },
        props.onResolve
          ? h("button", { onClick: () => props.onResolve(ex),
              style: { padding: "10px 18px", background: C.greenSoft, color: "#065f46", border: "1px solid " + C.greenBorder, borderRadius: 8, cursor: "pointer", fontWeight: 600, fontSize: 13 } }, "✓ Mark resolved")
          : h("button", { onClick: () => { close(); if (setPage) setPage("exceptions"); },
              style: { padding: "10px 18px", background: "none", color: C.text2, border: "1px solid " + C.border, borderRadius: 8, cursor: "pointer", fontWeight: 600, fontSize: 13 } }, "Manage in Exceptions Inbox →"),
        h("button", { onClick: close,
          style: { padding: "10px 18px", background: "none", border: "1px solid " + C.border, borderRadius: 8, cursor: "pointer", fontSize: 13, color: C.muted } }, "Close")));

    return h("div", {
      style: { position: "fixed", inset: 0, zIndex: 400, background: "rgba(13,32,64,0.6)", display: "flex", alignItems: "flex-start", justifyContent: "flex-end" },
      onClick: close,
    }, body);
  }

  window.ExceptionDetailPanel = ExceptionDetailPanel;
})();
