/* =============================================================
   page-risk.jsx - Risk & blockers
   ============================================================= */
function PageRisk({ model, onOpenSite, onOpenInPM, role }) {
  const [filterLevel, setFilterLevel] = React.useState("");
  const [search, setSearch] = React.useState("");
  const [editingRow, setEditingRow] = React.useState(null);
  const canEdit = role === "engineer" || role === "po" || role === "admin";

  // Determine the underlying entity kind that a risk row corresponds to.
  // G9: explicit enum check + console.warn on fallback, so we don't silently route
  // writes to the wrong entity when the source label drifts.
  const RISK_ENTITY_ENUM = ["underlay", "overlay", "isp", "newUnderlay"];
  const RISK_SOURCE_TO_ENTITY = {
    "underlay": "underlay",
    "overlay": "overlay",
    "isp": "isp",
    "new underlay": "newUnderlay",
  };
  function entityForRow(r) {
    if (r._riskEntity && RISK_ENTITY_ENUM.indexOf(r._riskEntity) >= 0) return r._riskEntity;
    const src = String(r._riskSource || "").toLowerCase().trim();
    if (RISK_SOURCE_TO_ENTITY[src]) return RISK_SOURCE_TO_ENTITY[src];
    if (typeof console !== "undefined") {
      console.warn("[page-risk] Unknown _riskEntity/_riskSource; defaulting to underlay", { _riskEntity: r._riskEntity, _riskSource: r._riskSource });
    }
    return "underlay";
  }
  function idHintForRow(r) {
    return r.linkRef || r.linkNum || r.siteCode || r.shortLabel || r.siteName || r.circuitId || "";
  }

  // G5: Risk editor fields per source entity. Only fields that exist in the entity's
  // PM contract are offered, so saves project cleanly to a workbook column on export.
  const RISK_FIELDS_BY_ENTITY = {
    underlay: [
      { key: "atRisk", label: "At risk?", type: "boolean" },
      { key: "riskLevel", label: "Risk level", type: "enum", options: ["Low", "Medium", "High"] },
      { key: "blocker", label: "Blocker", type: "longtext" },
      { key: "nextSteps", label: "Next steps", type: "longtext" },
      { key: "owner", label: "Owner", type: "text" },
    ],
    overlay: [
      { key: "migrationStatus", label: "Migration status", type: "enum", options: ["Not Started", "In Planning", "Scheduled", "Migrated", "Failed"] },
      { key: "migrationSchedule", label: "Migration schedule", type: "enum", options: ["Not Started", "In Planning", "Scheduled", "Migrated", "Failed"] },
      { key: "comment", label: "Comment (visible blocker / next step)", type: "longtext" },
    ],
    isp: [
      { key: "terminated", label: "Terminated?", type: "enum", options: ["Yes", "No", "Initiated", "On Hold", "In Progress"] },
      { key: "lead", label: "Lead / owner", type: "text" },
      { key: "comments", label: "Comments (blocker / next step)", type: "longtext" },
    ],
    newUnderlay: [],
  };

  function riskFieldsForRow(r) {
    const entity = entityForRow(r);
    if (entity !== "newUnderlay") return RISK_FIELDS_BY_ENTITY[entity] || RISK_FIELDS_BY_ENTITY.underlay;
    if (!r._riskField || !r._readinessKey) return [];
    return [{
      key: r._riskField,
      label: `Resolve ${r._readinessLabel || r._readinessKey}`,
      type: "enum",
      options: PRData.NEW_UNDERLAY_WORKFLOW_STATUS_OPTIONS || ["Not Started", "In Progress", "Done", "Blocked"],
    }];
  }

  function canEditRiskRow(r) {
    if (!canEdit) return false;
    const entity = entityForRow(r);
    return entity !== "newUnderlay" || !!(r._riskField && r._readinessKey);
  }

  function riskDetailCell(r) {
    const source = r._sourceLabel || [r.__sourceSheet, r.__sourceRowNumber ? `row ${r.__sourceRowNumber}` : ""].filter(Boolean).join(" ");
    return (
      <div style={{display: "flex", flexDirection: "column", gap: 3}}>
        <span>{r.blocker || r.nextSteps || <span className="muted">-</span>}</span>
        {r._readinessKey && (
          <span className="muted" style={{fontSize: 11}}>
            {r._readinessPhaseLabel || "New Underlay"} · {r._readinessLabel || r._readinessKey} <span className="mono">({r._riskField})</span> - current: {r._readinessValue || "-"}
          </span>
        )}
        {source && <span className="muted" style={{fontSize: 11}}>{source}</span>}
      </div>
    );
  }

  const atRiskRows = React.useMemo(() => {
    return PRData.allRiskRows(model, { level: filterLevel, search });
  }, [model, filterLevel, search]);

  const byRiskLevel = React.useMemo(() => {
    return PRData.riskLevelCounts(atRiskRows);
  }, [atRiskRows]);

  const blockerReasons = React.useMemo(() => PRData.blockerReasonBreakdown(atRiskRows), [atRiskRows]);

  const byOwner = React.useMemo(() => {
    const m = new Map();
    for (const u of atRiskRows) if (u.owner) m.set(u.owner, (m.get(u.owner) || 0) + 1);
    return [...m.entries()].sort((a, b) => b[1] - a[1]).map(([label, value]) => ({ label, value }));
  }, [atRiskRows]);

  const byCountry = React.useMemo(() => PRData.countryHotspots(atRiskRows), [atRiskRows]);

  const columns = [
    { key: "_riskSource", label: "Source", width: 110, render: (r) => <Pill kind={r._riskSource === "Underlay" ? "info" : "warn"}>{r._riskSource || "Workbook"}</Pill> },
    { key: "linkRef", label: "Ref", width: 90, cellClass: "mono strong", render: (r) => r.linkRef || r.siteCode || r.circuitId || <span className="muted">-</span> },
    { key: "siteName", label: "Site", render: (r) => (
        <div style={{display:"flex", flexDirection:"column"}}>
          <span className="strong">{r.siteName || r.siteCode || "-"}</span>
          <span className="muted" style={{fontSize: 11}}>{r.country} - {r.region}</span>
        </div>
      )},
    { key: "riskLevel", label: "Level", width: 120, render: (r) => <RiskPill level={r.riskLevel} atRisk={r.atRisk}/>, sortVal: (r) => r.riskLevel === "High" ? 3 : r.riskLevel === "Medium" ? 2 : r.riskLevel === "Low" ? 1 : 0 },
    { key: "blocker", label: "Blocker / detail", render: riskDetailCell },
    { key: "daysSlipped", label: "Slip", width: 70, cellClass: "num", render: (r) => {
        if (typeof r.daysSlipped !== "number") return <span className="muted">-</span>;
        return <span style={{color: r.daysSlipped > 60 ? "var(--risk)" : r.daysSlipped > 30 ? "var(--warn)" : "var(--ink-700)"}}>{r.daysSlipped}d</span>;
      }, sortVal: (r) => r.daysSlipped },
    { key: "owner", label: "Owner", width: 110, render: (r) => r.owner || <span className="muted">-</span> },
    { key: "circuitStatus", label: "Status", width: 200, render: (r) => <StatusCell value={r.circuitStatus} kind={r._riskSource === "Underlay" ? "circuit" : "task"}/> },
    { key: "_actions", label: "Actions", width: 168, sortable: false, render: (r) => (
        <div className="flex gap-sm" onClick={(e) => e.stopPropagation()}>
          {canEditRiskRow(r) && <button className="btn risk-readiness-action" data-entity={entityForRow(r)} data-field={r._riskField || ""} style={{ padding: "2px 8px", fontSize: 11 }} onClick={() => setEditingRow(r)}><Glyph name="edit" size={11}/> {r._riskField ? "Edit item" : "Edit status"}</button>}
          {onOpenInPM && <button className="btn ghost" style={{ padding: "2px 8px", fontSize: 11 }} onClick={() => onOpenInPM(entityForRow(r), idHintForRow(r))}>Open in PM</button>}
        </div>
      ) },
  ];

  return (
    <div className="page">
      <PageHeader
        title="Risk & blockers"
        subtitle="Workbook-backed risk, blocker, delay, and hold records across underlay, overlay, ISP, and new underlay."
        right={
          <div className="flex gap-sm">
            <FilterSelect label="Level" value={filterLevel} onChange={setFilterLevel} options={["High", "Medium", "Low"]}/>
            <SearchInput value={search} onChange={setSearch} placeholder="Search blockers, sites..."/>
          </div>
        }
      />

      <div className="grid g-4 mb-md">
        <KPI accent label="Total at risk" value={atRiskRows.length} hint="workbook risk/blocker records" delta=""/>
        <KPI label="High risk" value={byRiskLevel.High || 0} hint="active high-level" delta=""/>
        <KPI label="Medium risk" value={byRiskLevel.Medium || 0} hint="" delta=""/>
        <KPI label="Low risk" value={byRiskLevel.Low || 0} hint="" delta=""/>
      </div>

      <div className="grid g-3 mb-md">
        <div className="card">
          <div className="card-h"><div className="title">Blocker reasons</div></div>
          {blockerReasons.length === 0 ? <Empty title="No blockers recorded."/> : <BarChart data={blockerReasons} accent="var(--risk)"/>}
        </div>
        <div className="card">
          <div className="card-h"><div className="title">Country hotspots</div></div>
          {byCountry.length === 0 ? <Empty title="No country data."/> : <BarChart data={byCountry}/>}
        </div>
        <div className="card">
          <div className="card-h"><div className="title">Owners</div></div>
          {byOwner.length === 0 ? <Empty title="No owners assigned."/> : <BarChart data={byOwner.map((o) => ({...o, color: "var(--info)"}))}/>}
        </div>
      </div>

      <div className="table-wrap">
        <div className="table-toolbar">
          <span className="mono" style={{fontSize: 11.5, color: "var(--ink-500)"}}>{atRiskRows.length} risk/blocker records</span>
        </div>
        <DataTable columns={columns} rows={atRiskRows} onRowClick={(r) => onOpenSite({ site: { siteName: r.siteName, siteCode: r.siteCode, country: r.country, region: r.region, criticality: r.criticality }, link: r._riskEntity === "underlay" ? r : null })} maxHeight={"60vh"}/>
      </div>

      {editingRow && (
        <TrackerRowEditor
          row={editingRow}
          entity={entityForRow(editingRow)}
          idResolver={(r) => PRData.resolveOperationalEntityId(entityForRow(r), r, model)}
          fields={riskFieldsForRow(editingRow)}
          canEdit={canEdit}
          openInPM={onOpenInPM}
          onClose={() => setEditingRow(null)}
          onSaved={() => {/* GA-13: autosave — model re-renders via PMClient.subscribe; editor stays open */}}
        />
      )}
    </div>
  );
}

window.PageRisk = PageRisk;
