/* ═══════════════════════════════════════════════════════════
   OpAgent | Anywhere — cross-functional workflow module
   Eligibility · Prior Auth · Coding · Exceptions
   Phase-1 buildout: read-first queueing with explicit reason codes
   + ownership/status updates and exception filtering
   ═══════════════════════════════════════════════════════════ */

const { useState, useEffect } = React;

function wfMoney(v){
  return Number.isFinite(+v) ? ("$" + Math.round(+v).toLocaleString("en-US")) : "";
}
function isoToday(){
  const d = new Date();
  return `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,"0")}-${String(d.getDate()).padStart(2,"0")}`;
}

function wfAgeDays(dos){
  if(!dos) return null;
  let d = null;
  if (/^\d{4}-\d{2}-\d{2}$/.test(dos)) d = new Date(dos+"T12:00:00");
  else {
    const m = String(dos).match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/);
    if(m) d = new Date(Number(m[3]), Number(m[1])-1, Number(m[2]), 12, 0, 0);
  }
  if(!d || Number.isNaN(+d)) return null;
  const days = Math.floor((Date.now() - +d) / 86400000);
  return Math.max(0, days);
}

function WfKpi({ label, value, tone }){
  return (
    <div className={"tile " + (tone || "")}>
      <div className="tl">{label}</div>
      <div className="tv">{value}</div>
      <div className="tsub">active cases</div>
    </div>
  );
}

function wfEligibilityEvidence(a){
  if(!a) return "";
  const checked = new Date(a.checkedAt);
  const age = Number.isFinite(+checked) ? `${Math.max(0, Math.round((Date.now()-+checked)/60000))}m ago` : "timestamp unknown";
  const source = a.sourceLabel || a.source || "unknown source";
  const fresh = a.realtime
    ? "fresh live run observed"
    : (a.freshTriggered ? "fresh trigger attempted; 271 snapshot used" : "271 snapshot used");
  const coverage = a.hasData ? (a.active ? "active" : "inactive/unclear") : "no benefit data";
  const plan = [a.planName, a.memberId ? `member ${a.memberId}` : "", a.groupNumber ? `group ${a.groupNumber}` : "", a.startDate ? `start ${a.startDate}` : ""].filter(Boolean).join(" · ");
  return `evidence: ${source} · ${coverage} · ${fresh} · checked ${age} · ${a.elapsedMs}ms${plan ? " · " + plan : ""}`;
}

function wfShortMemberId(memberId){
  const raw = String(memberId || "").trim();
  if(!raw) return "";
  let decoded = raw;
  try { decoded = decodeURIComponent(raw); } catch (_) {}
  decoded = decoded.replace(/\s+/g, " ").trim();
  return decoded.length > 12 ? `${decoded.slice(0, 1)}...` : decoded;
}

function wfEligibilityDetailsFromNote(note){
  const n = String(note || "").trim();
  if(!n) return "";
  const main = n.replace(/\.$/, "").split(/\. Route\b/i)[0];
  return main
    .replace(/^Eligibility\s+ACTIVE\s+via\s+271\s*·?\s*/i, "")
    .replace(/^Eligibility\s+INACTIVE\/unclear\s+via\s+271\s*·?\s*/i, "")
    .replace(/^Eligibility\s+not\s+confirmed\s*[—-]\s*/i, "")
    .replace(/member\s+([^·]+)/i, (_, id)=>`member ${wfShortMemberId(id)}`)
    .trim();
}

function wfEligibilityResult(row, lane){
  if(lane !== "eligibility" || (!row.eligibilityAudit && !row.note)) return null;
  const audit = row.eligibilityAudit;
  const note = String(row.note || (audit && audit.noteApplied) || "");
  const looksEligibilityNote = /^Eligibility\s+(ACTIVE|INACTIVE\/unclear|not confirmed)\b/i.test(note);
  if(!audit && !looksEligibilityNote) return null;

  let tone = "neutral";
  let label = "No data";
  if(audit) {
    if(audit.hasData && audit.active) {
      tone = "active";
      label = "Active";
    } else if(audit.hasData) {
      tone = /needs/i.test(audit.statusApplied || "") ? "review" : "inactive";
      label = tone === "review" ? "Needs review" : "Inactive";
    }
  } else if(/^Eligibility\s+ACTIVE\b/i.test(note)) {
    tone = "active";
    label = "Active";
  } else if(/^Eligibility\s+INACTIVE\/unclear\b/i.test(note)) {
    tone = "review";
    label = "Needs review";
  } else if(/^Eligibility\s+INACTIVE\b/i.test(note)) {
    tone = "inactive";
    label = "Inactive";
  }

  let details = wfEligibilityDetailsFromNote(note);
  if(!details && audit) {
    const source = audit.realtime
      ? "source live run via DrChrono (fresh trigger observed)"
      : "source 271 snapshot (fresh trigger not observed)";
    details = [
      audit.planName,
      audit.memberId ? `member ${wfShortMemberId(audit.memberId)}` : "",
      audit.startDate ? `start ${audit.startDate}` : "",
      source,
    ].filter(Boolean).join(" · ");
  }

  return { tone, label, details: details || note };
}

function wfRunErrorMessage(r){
  const raw = String((r && r.error) || "Soft Check failed").trim();
  if(/timed?_?out|timed out/i.test(raw)) return "Soft Check timed out. Please try again.";
  if(/writeback disabled/i.test(raw)) return "Soft Check blocked: workflow writeback is disabled.";
  return raw.replace(/_/g, " ");
}

function wfDemographicsPill(status){
  if(status === "success") return { tone:"active", label:"Demographics success" };
  if(status === "blocked") return { tone:"review", label:"Demographics blocked" };
  if(status === "failed") return { tone:"error", label:"Demographics failed" };
  if(status === "running") return { tone:"neutral", label:"Demographics running" };
  return { tone:"neutral", label:"Demographics not run" };
}

function wfDemographicsSummary(run, audit){
  if(run && run.message) return run.message;
  if(audit && audit.summary) return audit.summary;
  return "Run pull+fill to write eligibility demographics into insurance fields.";
}

function wfApplyEligibilityRun(W, rowId, r){
  if(!W || !W.queues || !r) return W;
  const audit = r.audit ? Object.assign({}, r.audit, {
    sourceLabel: r.audit.sourceLabel || r.audit.source || "eligibility audit",
  }) : undefined;
  const patch = r.patch || {};
  const mergeRow = (row)=>row.id === rowId ? Object.assign({}, row, patch, audit ? { eligibilityAudit: audit } : {}) : row;
  return Object.assign({}, W, {
    queues: Object.assign({}, W.queues, {
      eligibility: ((W.queues && W.queues.eligibility) || []).map(mergeRow),
      exceptions: ((W.queues && W.queues.exceptions) || []).map(mergeRow),
    }),
  });
}

/* ── Eligibility-pipeline read helpers (derive UI state from data the pipeline
   ALREADY produces — no invented backend signals). ── */
function wfPipelineResult(pipelineRun){
  return pipelineRun && pipelineRun.status === "done" && pipelineRun.result ? pipelineRun.result : null;
}
function wfStageDetail(result, key){
  if(!result || !Array.isArray(result.stages)) return null;
  const s = result.stages.find((st)=>st.key === key);
  return s ? (s.detail || null) : null;
}
function wfAbstain(result){
  if(!result || result.terminalStatus === "blank") return null;
  const tpl = wfStageDetail(result, "template_fill");
  const competing = tpl && Array.isArray(tpl.ambiguousAmong) ? tpl.ambiguousAmong : [];
  const reasons = Array.isArray(result.pendingCraig) ? result.pendingCraig : [];
  return { reasons, competing, primary: reasons[0] || "Determination incomplete — routing to Craig." };
}
function wfRecommended(pipelineRun){
  const result = wfPipelineResult(pipelineRun);
  if(pipelineRun && pipelineRun.status === "running") return { key:"running", label:"Running…", tone:"primary", disabled:true };
  if(!result) return { key:"run", label:"Run eligibility check", tone:"primary" };
  if(result.terminalStatus === "blank") return { key:"arm", label:"Write determination + advance", tone:"primary", ready:true };
  const ab = wfAbstain(result) || { reasons:[], competing:[] };
  const ambiguous = ab.competing && ab.competing.length;
  const identity = (ab.reasons||[]).some((r)=>/identity|reconnect|session|mismatch|could not be identified/i.test(r));
  const label = ambiguous ? "Review — confirm plan"
    : identity ? "Review — identity uncertain"
    : "Review — routing to Craig";
  return { key:"review", label, tone:"review" };
}
function wfSweepState(pipelineRun){
  const result = wfPipelineResult(pipelineRun);
  if(pipelineRun && pipelineRun.status === "running") return "active";
  if(pipelineRun && pipelineRun.status === "error") return "error";
  if(!result) return "pending";
  return result.terminalStatus === "blank" ? "signed" : "craig";
}

function WfEligibilityActions({ row, busy, pipelineRun, armed, isExpanded, onRunPipeline, onArm, onToggleEvidence, onUpdate, onRunEligibility, onRunDemographics }){
  const [menuOpen, setMenuOpen] = useState(false);
  const rec = wfRecommended(pipelineRun);
  const result = wfPipelineResult(pipelineRun);
  const running = pipelineRun && pipelineRun.status === "running";
  const closeMenu = ()=>setMenuOpen(false);
  function primaryClick(){
    if(rec.key === "run" || rec.key === "running") return onRunPipeline(row);
    if(rec.key === "arm") return onArm(row);
    return onToggleEvidence(row); // review → open evidence to inspect/route
  }
  return (
    <div style={{ marginTop:10, display:"flex", gap:8, flexWrap:"wrap", alignItems:"center" }}>
      <button
        className={"pill-btn primary " + (rec.tone === "review" ? "review " : "") + (running ? "loading" : "")}
        disabled={busy || rec.disabled || !row.patientRef}
        onClick={primaryClick}
      >
        {running && <span className="wf-mini-spinner" aria-hidden="true"></span>}
        {rec.label}
      </button>

      {result && (
        <button className="pill-btn" disabled={busy} onClick={()=>onToggleEvidence(row)}>
          {isExpanded ? "Hide evidence" : "View evidence"}
        </button>
      )}

      <div className="wf-overflow">
        <button className="pill-btn" disabled={busy} onClick={()=>setMenuOpen((v)=>!v)} aria-label="More actions">···</button>
        {menuOpen && (
          <>
            <div style={{ position:"fixed", inset:0, zIndex:25 }} onClick={closeMenu}></div>
            <div className="wf-overflow-menu">
              <button disabled={busy || running} onClick={()=>{ closeMenu(); onRunPipeline(row); }}>Re-run fresh determination</button>
              <button disabled={busy || running || !row.patientRef} onClick={()=>{ closeMenu(); onRunEligibility(row); }}>Soft check only (271)</button>
              <button disabled={busy || running || !row.patientRef} onClick={()=>{ closeMenu(); onRunDemographics(row); }}>Demographics pull+fill</button>
              {row.patientUrl && <a href={row.patientUrl} target="_blank" rel="noreferrer" onClick={closeMenu}>Open in DrChrono ↗</a>}
            </div>
          </>
        )}
      </div>

      <button
        className="pill-btn muted-alert"
        disabled={busy}
        onClick={()=>onUpdate(row.id, { status:"needs-human-review", updatedBy:"opagent-ui" })}
        title="Escape hatch — hand this row to Craig"
      >
        Send to Craig
      </button>

      {rec.ready && (
        <button
          className={"pill-btn arm " + (armed ? "on" : "")}
          disabled={busy}
          onClick={()=>onArm(row)}
        >
          {armed ? "✓ Armed (will write)" : "Arm this write"}
        </button>
      )}
    </div>
  );
}

function WfAbstainBlock({ result }){
  const ab = wfAbstain(result);
  if(!ab) return null;
  return (
    <div className="wf-abstain">
      <div className="wf-abstain-kicker">⏸ Stopped here — routing to Craig</div>
      <div className="wf-abstain-reason">{ab.primary}</div>
      {!!(ab.competing && ab.competing.length) && (
        <div className="wf-compete">
          <div style={{ fontFamily:"var(--fm)", fontSize:10, letterSpacing:".08em", textTransform:"uppercase", color:"var(--forest)" }}>
            Competing Grid rows it saw — confirm which:
          </div>
          {ab.competing.map((nm, i)=>(<div key={i} className="wf-compete-row">{nm}</div>))}
        </div>
      )}
      {ab.reasons && ab.reasons.length > 1 && (
        <div style={{ marginTop:7, fontFamily:"var(--fs)", fontSize:11.5, color:"var(--ink-soft)" }}>
          Also: {ab.reasons.slice(1).join("; ")}.
        </div>
      )}
    </div>
  );
}

function WfProposeBlock({ result, armed }){
  if(!result || result.terminalStatus !== "blank") return null;
  const sn = wfStageDetail(result, "signed_note_writeback") || {};
  const writes = Array.isArray(sn.demographicsWriteCandidatesPreview) ? sn.demographicsWriteCandidatesPreview : [];
  const adv = result.statusAdvance || {};
  return (
    <div className="wf-propose">
      <div className="wf-propose-head">
        <span className="wf-eligibility-pill active">Proposed: determination ready</span>
        <span className="wf-dry-pill">Dry-propose · not written</span>
        {adv.toStatusLabel && (
          <span className="wf-propose-target">advance billing status → <b>{adv.toStatusLabel}</b></span>
        )}
      </div>
      <div style={{ marginTop:7, fontFamily:"var(--fm)", fontSize:11, color:"var(--ink-soft)", letterSpacing:".02em" }}>
        proposed write target{writes.length === 1 ? "" : "s"}: {writes.length
          ? writes.map((w)=>`${w.logicalField}="${w.value}"`).join(" · ")
          : "signed note only (no demographics fields returned)"}
      </div>
      {result.note && (
        <details>
          <summary style={{ cursor:"pointer", marginTop:8, fontFamily:"var(--fm)", fontSize:10.5, letterSpacing:".06em", textTransform:"uppercase", color:"var(--gilt-dark)" }}>
            Proposed signed note (preview — not written)
          </summary>
          <pre className="wf-note-preview" style={{ marginTop:8, whiteSpace:"pre-wrap", fontFamily:"var(--fm)", fontSize:11, color:"var(--ink)", background:"var(--pure)", border:"1px solid var(--canvas-dark)", borderRadius:7, padding:10, maxHeight:230, overflow:"auto" }}>{result.note}</pre>
        </details>
      )}
      {armed && (
        <div className="wf-armed-banner">
          ✓ Armed by you. Server writeback is disarmed in this pass (armWrites=0) — no chart write performed.
          Enable writeback to commit this determination + status advance.
        </div>
      )}
    </div>
  );
}

function WfEvidenceDrawer({ result }){
  if(!result) return null;
  const tpl = wfStageDetail(result, "template_fill") || {};
  const soft = wfStageDetail(result, "soft_check") || {};
  const sn = wfStageDetail(result, "signed_note_writeback") || {};
  const writes = Array.isArray(sn.demographicsWriteCandidatesPreview) ? sn.demographicsWriteCandidatesPreview : [];
  const adv = result.statusAdvance || {};
  const grid = tpl.gridRow || null;
  const competing = Array.isArray(tpl.ambiguousAmong) ? tpl.ambiguousAmong : [];
  const res = tpl.resolution || {};
  return (
    <div className="wf-ev">
      <div className="wf-ev-sec">
        <div className="wf-ev-h">Generated determination note</div>
        <pre>{result.note || "(no note produced)"}</pre>
      </div>
      <div className="wf-ev-sec">
        <div className="wf-ev-h">Matched Insurance Grid row</div>
        {grid ? (
          <div className="wf-ev-body">
            <b>{grid.name || grid.label}</b>{grid.id ? ` · id ${grid.id}` : ""}
            {tpl.matchReason && <div style={{ marginTop:4, fontFamily:"var(--fm)", fontSize:11, color:"var(--ink-soft)" }}>{tpl.matchReason}</div>}
            {res.sourceUsed && <div style={{ marginTop:4, fontFamily:"var(--fm)", fontSize:10.5, color:"var(--ink-faint)", letterSpacing:".04em", textTransform:"uppercase" }}>source {res.sourceUsed}</div>}
          </div>
        ) : competing.length ? (
          <div className="wf-ev-body">
            <span style={{ color:"var(--gilt-dark)", fontWeight:600 }}>Abstained — competing rows:</span>
            <div className="wf-compete" style={{ marginTop:6 }}>
              {competing.map((nm, i)=>(<div key={i} className="wf-compete-row">{nm}</div>))}
            </div>
            {tpl.matchReason && <div style={{ marginTop:6, fontFamily:"var(--fm)", fontSize:11, color:"var(--ink-soft)" }}>{tpl.matchReason}</div>}
          </div>
        ) : (
          <div className="wf-ev-body" style={{ color:"var(--ink-soft)" }}>{tpl.matchReason || "No Grid row matched — first-time discovery routed to Craig."}</div>
        )}
      </div>
      <div className="wf-ev-sec">
        <div className="wf-ev-h">Soft check (DrChrono 271)</div>
        <div className="wf-kv">
          <span className="k">coverage</span><span className="v">{soft.hasData ? (soft.active ? "ACTIVE" : "inactive/unclear") : "no benefit data"}</span>
          {soft.planName && (<><span className="k">plan</span><span className="v">{soft.planName}</span></>)}
          {soft.memberId && (<><span className="k">member</span><span className="v">{wfShortMemberId(soft.memberId)}</span></>)}
          {soft.groupNumber && (<><span className="k">group</span><span className="v">{soft.groupNumber}</span></>)}
          {soft.startDate && (<><span className="k">start</span><span className="v">{soft.startDate}</span></>)}
          <span className="k">freshness</span><span className="v">{soft.realtime ? "live run observed" : "271 snapshot"}</span>
          {soft.sessionReconnectNeeded && (<><span className="k">session</span><span className="v" style={{ color:"var(--gilt-dark)" }}>needs reconnect</span></>)}
          {Number.isFinite(+soft.elapsedMs) && (<><span className="k">latency</span><span className="v">{soft.elapsedMs}ms</span></>)}
        </div>
      </div>
      <div className="wf-ev-sec">
        <div className="wf-ev-h">Proposed write-target fields</div>
        {writes.length ? (
          <div className="wf-kv">
            {writes.map((w, i)=>(<React.Fragment key={i}><span className="k">{w.logicalField}</span><span className="v">{w.value}</span></React.Fragment>))}
          </div>
        ) : (
          <div className="wf-ev-body" style={{ color:"var(--ink-soft)" }}>No demographics fields staged (signed note only).</div>
        )}
        <div style={{ marginTop:8, fontFamily:"var(--fm)", fontSize:11, color:"var(--ink-soft)" }}>
          status advance: <b style={{ color:"var(--ink)" }}>{adv.fromStatus || "—"} → {adv.toStatusLabel || "—"}</b> · {adv.recommended ? "recommended" : "held"} · {adv.reason}
        </div>
      </div>
      <div className="wf-ev-sec">
        <div className="wf-ev-h">Audit trail</div>
        <div className="wf-kv">
          <span className="k">terminal status</span><span className="v">{result.terminalStatus}</span>
          <span className="k">signer</span><span className="v">{result.signer}</span>
          <span className="k">ran at</span><span className="v">{result.ranAt}</span>
          <span className="k">determination</span><span className="v">{result.synthetic ? "SYNTHETIC test data" : "live portal read"}</span>
          {res.sourceUsed && (<><span className="k">grid source</span><span className="v">{res.sourceUsed}{Array.isArray(res.attempted) && res.attempted.length ? ` (tried ${res.attempted.join(", ")})` : ""}</span></>)}
        </div>
      </div>
    </div>
  );
}

function WfRow({ row, lane, onUpdate, onRunEligibility, onRunDemographics, onRunPipeline, onArm, onToggleEvidence, busy, eligibilityRun, demographicsRun, pipelineRun, armed, isExpanded, sweepState }){
  const priority = (row.priority || "").toLowerCase();
  const priColor = priority === "high" ? "#9A2A2A" : priority === "medium" ? "#8A6B1E" : "#3a5f4a";
  const ageDays = wfAgeDays(row.dos);
  const ageTone = ageDays != null && ageDays >= 30 ? "#9A2A2A" : ageDays != null && ageDays >= 7 ? "#8A6B1E" : "var(--ink-faint)";
  const [showEvidence, setShowEvidence] = useState(false);
  const evidenceText = row.eligibilityAudit ? wfEligibilityEvidence(row.eligibilityAudit) : "";
  const eligibilityResult = wfEligibilityResult(row, lane);
  const isChecking = eligibilityRun && eligibilityRun.status === "running";
  const runDone = eligibilityRun && eligibilityRun.status === "success";
  const runError = eligibilityRun && eligibilityRun.status === "error";
  const demographicsAudit = row.eligibilityAudit && row.eligibilityAudit.demographics;
  const demoStatus = demographicsRun ? demographicsRun.status : (demographicsAudit ? demographicsAudit.status : "not_run");
  const demoPill = wfDemographicsPill(demoStatus);
  const demoSummary = wfDemographicsSummary(demographicsRun, demographicsAudit);
  const demoRunning = demographicsRun && demographicsRun.status === "running";
  const pipelineResult = wfPipelineResult(pipelineRun);
  const rowClass = "wfr"
    + (sweepState === "active" ? " wf-sweeping" : "")
    + (armed ? " wf-armed" : "");
  return (
    <div className={rowClass} style={{ border:"1px solid rgba(22,61,43,.10)", borderRadius:10, padding:"10px 12px", background:"#fff", transition:"box-shadow .25s, border-color .25s" }}>
      <div style={{ display:"flex", justifyContent:"space-between", gap:10, alignItems:"baseline" }}>
        <div style={{ fontFamily:"var(--fs)", fontSize:13, color:"var(--ink)" }}>
          <b>{row.patientName || "Unknown patient"}</b>
          {row.dos && <span style={{ color:"var(--ink-faint)" }}> · DOS {row.dos}</span>}
          {row.claimId && <span style={{ color:"var(--ink-faint)" }}> · Claim #{row.claimId}</span>}
          {row.payer && <span style={{ color:"var(--ink-faint)" }}> · {row.payer}</span>}
        </div>
        <div style={{ display:"flex", gap:8, alignItems:"center" }}>
          {lane==="eligibility" && pipelineResult && (
            <span className={"wf-eligibility-pill " + (pipelineResult.terminalStatus === "blank" ? "active" : "review")}>
              {pipelineResult.terminalStatus === "blank" ? "Signed" : "Pending Craig"}
            </span>
          )}
          {lane==="eligibility" && pipelineRun && pipelineRun.status === "running" && (
            <span className="wf-eligibility-pill neutral">Active…</span>
          )}
          <span style={{ fontFamily:"var(--fm)", fontSize:10, letterSpacing:".06em", textTransform:"uppercase", color:priColor }}>
            {priority || "low"}
          </span>
        </div>
      </div>
      <div style={{ marginTop:6, fontFamily:"var(--fs)", fontSize:12, color:"var(--ink)" }}>
        <b>{row.title}</b> — {row.detail}
      </div>
      <div style={{ marginTop:8, display:"flex", gap:8, flexWrap:"wrap", alignItems:"center", fontFamily:"var(--fm)", fontSize:10, letterSpacing:".05em", color:"var(--ink-faint)", textTransform:"uppercase" }}>
        {row.reasonCode && <span style={{ color:"#9A2A2A", fontWeight:700 }}>reason {row.reasonCode}</span>}
        {ageDays != null && <span style={{ color:ageTone, fontWeight:600 }}>age {ageDays}d</span>}
        {!!row.amount && <span style={{ color:"var(--ink)" }}>{wfMoney(row.amount)}</span>}
        {eligibilityResult ? (
          <span className="wf-eligibility-result">
            <span className={"wf-eligibility-pill " + eligibilityResult.tone}>{eligibilityResult.label}</span>
            {eligibilityResult.details && <span className="wf-eligibility-details">{eligibilityResult.details}</span>}
          </span>
        ) : (
          row.note && <span style={{ color:"var(--ink-soft)", textTransform:"none" }}>note: {row.note}</span>
        )}
        {lane==="eligibility" && demoStatus !== "not_run" && (
          <span className="wf-eligibility-result">
            <span className={"wf-eligibility-pill " + demoPill.tone}>{demoPill.label}</span>
            <span className="wf-eligibility-details">{demoSummary}</span>
          </span>
        )}
      </div>
      {(isChecking || runDone || runError) && (
        <div className={"wf-eligibility-status " + eligibilityRun.status}>
          <span className={"wf-eligibility-pill " + (runError ? "error" : runDone ? "active" : "neutral")}>
            {runError ? "Soft Check failed" : runDone ? "Soft Check complete" : "Soft-checking"}
          </span>
          <span>{eligibilityRun.message}</span>
        </div>
      )}
      {lane==="eligibility" && pipelineRun && pipelineRun.status === "error" && (
        <div className="wf-eligibility-status error">
          <span className="wf-eligibility-pill error">Pipeline failed</span>
          <span>{pipelineRun.message || "Eligibility pipeline failed."}</span>
        </div>
      )}

      {lane==="eligibility" ? (
        <>
          <WfEligibilityActions
            row={row} busy={busy} pipelineRun={pipelineRun} armed={armed} isExpanded={isExpanded}
            onRunPipeline={onRunPipeline} onArm={onArm} onToggleEvidence={onToggleEvidence}
            onUpdate={onUpdate} onRunEligibility={onRunEligibility} onRunDemographics={onRunDemographics}
          />
          <WfAbstainBlock result={pipelineResult} />
          <WfProposeBlock result={pipelineResult} armed={armed} />
          {isExpanded && <WfEvidenceDrawer result={pipelineResult} />}
        </>
      ) : (
        <div style={{ marginTop:8, display:"flex", gap:8, flexWrap:"wrap", alignItems:"center" }}>
          {row.eligibilityAudit && (
            <button className="pill-btn" disabled={busy} onClick={()=>setShowEvidence(!showEvidence)}>
              {showEvidence ? "Hide evidence" : "View evidence"}
            </button>
          )}
          <button className="pill-btn muted-alert" disabled={busy} onClick={()=>onUpdate(row.id, { status:"needs-human-review", updatedBy:"opagent-ui" })}>Send to Craig</button>
          {row.patientUrl && (
            <a className="pill-btn" href={row.patientUrl} target="_blank" rel="noreferrer">Open DrChrono</a>
          )}
        </div>
      )}

      {showEvidence && row.eligibilityAudit && (
        <div
          title={row.eligibilityAudit.noteApplied || ""}
          style={{ marginTop:8, fontFamily:"var(--fs)", fontSize:12, color:"var(--ink-soft)", lineHeight:1.45 }}
        >
          {evidenceText}
          {demographicsAudit && (
            <div style={{ marginTop:8 }}>
              <div><b>Demographics pull+fill:</b> {demographicsAudit.summary}</div>
              {!!(demographicsAudit.outcomes && demographicsAudit.outcomes.length) && (
                <div style={{ marginTop:4 }}>
                  {demographicsAudit.outcomes.map((o, i)=>(
                    <div key={i}>
                      {o.label} · {o.action}{o.targetField ? ` (${o.targetField})` : ""}{o.reason ? ` · ${o.reason}` : ""}
                    </div>
                  ))}
                </div>
              )}
              {demographicsAudit.evidenceUrl && (
                <div style={{ marginTop:4 }}>
                  <a href={demographicsAudit.evidenceUrl} target="_blank" rel="noreferrer">Verify demographics in DrChrono</a>
                </div>
              )}
            </div>
          )}
        </div>
      )}
    </div>
  );
}

function WorkflowsModule(){
  const seed = window.DEMO.workflows || { kpis:{}, queues:{}, generatedAt:"" };
  const [W, setW] = useState(seed);
  const [lane, setLane] = useState("eligibility");
  const [date, setDate] = useState((seed.meta && seed.meta.date) || isoToday());
  const [reasonFilter, setReasonFilter] = useState("all");
  const [ownerFilter, setOwnerFilter] = useState("all");
  const [statusFilter, setStatusFilter] = useState("all");
  const [busyId, setBusyId] = useState("");
  const [eligibilityRuns, setEligibilityRuns] = useState({});
  const [demographicsRuns, setDemographicsRuns] = useState({});
  const [pipelineRuns, setPipelineRuns] = useState({});
  const [armedRows, setArmedRows] = useState({});
  const [expandedRows, setExpandedRows] = useState({});
  const [armAllClean, setArmAllClean] = useState(false);
  const [sweep, setSweep] = useState({ running:false, total:0, done:0, currentId:"" });
  const [bench, setBench] = useState(null);
  const controls = W.controls || {};
  const meta = W.meta || {};
  const reasonCounts = meta.reasonCounts || {};
  const rowsMismatch = (meta.scheduleRows != null && meta.eligibilityRows != null)
    ? meta.scheduleRows !== meta.eligibilityRows
    : false;
  const dayTxt = date ? new Date(date+"T12:00:00").toLocaleDateString([], { weekday:"short", month:"short", day:"numeric", year:"numeric" }) : "";

  async function refresh(nextDate){
    const useDate = nextDate || date;
    const j = await window.Adapters.workflowsDashboard(useDate);
    if (j && j.queues) {
      window.DEMO.workflows = j;
      setW(j);
      if (j.meta && j.meta.date) setDate(j.meta.date);
    }
  }
  async function updateItem(id, patch){
    setBusyId(id);
    const laneOf = (queueMap.eligibility||[]).some((r)=>r.id===id) ? "eligibility"
      : (queueMap.priorAuth||[]).some((r)=>r.id===id) ? "prior_auth"
      : (queueMap.coding||[]).some((r)=>r.id===id) ? "coding"
      : "exceptions";
    const r = await window.Adapters.workflowsUpdate(id, Object.assign({}, patch, { lane: laneOf }));
    if (!r || r.error) {
      window.alert((r && r.error) ? ("Update blocked: " + r.error) : "Update failed");
      setBusyId("");
      return;
    }
    await refresh();
    setBusyId("");
  }
  async function runEligibility(row){
    setBusyId(row.id);
    setEligibilityRuns((m)=>Object.assign({}, m, {
      [row.id]: {
        status: "running",
        message: "Running Soft Check (271) via DrChrono — confirms active/plan/member/group/start only...",
      },
    }));
    try {
      const r = await window.Adapters.workflowsRunEligibility(row.id, {
        lane: "eligibility",
        patientRef: row.patientRef,
        appointmentId: row.claimId,
        payer: row.payer,
        updatedBy: "opagent-ui",
      });
      if (!r || r.error) {
        setEligibilityRuns((m)=>Object.assign({}, m, {
          [row.id]: {
            status: "error",
            message: wfRunErrorMessage(r),
          },
        }));
        setBusyId("");
        return;
      }
      setW((current)=>{
        const next = wfApplyEligibilityRun(current, row.id, r);
        window.DEMO.workflows = next;
        return next;
      });
      setEligibilityRuns((m)=>Object.assign({}, m, {
        [row.id]: {
          status: "success",
          message: "Soft Check (271) result applied to this row.",
        },
      }));
      await refresh(date);
    } catch (e) {
      setEligibilityRuns((m)=>Object.assign({}, m, {
        [row.id]: {
          status: "error",
          message: wfRunErrorMessage({ error: e && e.message }),
        },
      }));
    } finally {
      setBusyId("");
    }
  }
  async function runDemographics(row){
    setBusyId(row.id);
    setDemographicsRuns((m)=>Object.assign({}, m, {
      [row.id]: {
        status: "running",
        message: "Pulling eligibility + attempting demographics fill...",
      },
    }));
    try {
      const r = await window.Adapters.workflowsRunEligibility(row.id, {
        lane: "eligibility",
        patientRef: row.patientRef,
        appointmentId: row.claimId,
        payer: row.payer,
        updatedBy: "opagent-ui",
        runDemographicsFill: true,
      });
      if (!r || r.error) {
        setDemographicsRuns((m)=>Object.assign({}, m, {
          [row.id]: {
            status: "failed",
            message: wfRunErrorMessage(r),
          },
        }));
        setBusyId("");
        return;
      }
      const demo = r.demographics || (r.audit && r.audit.demographics);
      const nextStatus = demo && demo.status ? demo.status : "blocked";
      const nextMessage = demo && demo.summary
        ? demo.summary
        : "Demographics pull+fill did not produce a writable result.";
      setW((current)=>{
        const next = wfApplyEligibilityRun(current, row.id, r);
        window.DEMO.workflows = next;
        return next;
      });
      setDemographicsRuns((m)=>Object.assign({}, m, {
        [row.id]: {
          status: nextStatus,
          message: nextMessage,
        },
      }));
      await refresh(date);
    } catch (e) {
      setDemographicsRuns((m)=>Object.assign({}, m, {
        [row.id]: {
          status: "failed",
          message: wfRunErrorMessage({ error: e && e.message }),
        },
      }));
    } finally {
      setBusyId("");
    }
  }
  async function runBenchmark(){
    const r = await window.Adapters.workflowsEligibilityBenchmark(date, 10, true);
    if (!r || r.error) {
      window.alert((r && r.error) ? ("Benchmark failed: " + r.error) : "Benchmark failed");
      return;
    }
    setBench(r);
  }
  // Run the FULL determination pipeline for one row (read-only / dry-propose —
  // stage 5 writeback is disarmed server-side). Returns the result for sweeps.
  async function runPipeline(row){
    setPipelineRuns((m)=>Object.assign({}, m, { [row.id]: { status:"running" } }));
    try {
      const r = await window.Adapters.eligibilityRun(row.id, {
        patientRef: row.patientRef,
        appointmentId: row.claimId,
        payer: row.payer,
        patientName: row.patientName,
      });
      if (!r || r.error || !r.result) {
        setPipelineRuns((m)=>Object.assign({}, m, { [row.id]: { status:"error", message:(r && r.error) || "Eligibility pipeline failed" } }));
        return null;
      }
      setPipelineRuns((m)=>Object.assign({}, m, { [row.id]: { status:"done", result:r.result } }));
      return r.result;
    } catch (e) {
      setPipelineRuns((m)=>Object.assign({}, m, { [row.id]: { status:"error", message:(e && e.message) || "Eligibility pipeline failed" } }));
      return null;
    }
  }
  function toggleArm(row){
    setArmedRows((m)=>Object.assign({}, m, { [row.id]: !m[row.id] }));
  }
  function toggleEvidence(row){
    setExpandedRows((m)=>Object.assign({}, m, { [row.id]: !m[row.id] }));
  }
  // The wow beat: work the whole filtered eligibility bucket in sequence, live.
  // DRY-PROPOSE — runs the determination pipeline per row (no writes). Clean rows
  // are auto-armed only when the global "arm all clean rows" toggle is ON.
  async function runSweep(sweepRows){
    if (sweep.running || !sweepRows.length) return;
    setSweep({ running:true, total:sweepRows.length, done:0, currentId:"" });
    for (let i = 0; i < sweepRows.length; i++) {
      const row = sweepRows[i];
      if (!row.patientRef) { setSweep((s)=>Object.assign({}, s, { done:i+1 })); continue; }
      setSweep((s)=>Object.assign({}, s, { currentId:row.id }));
      const result = await runPipeline(row);
      if (armAllClean && result && result.terminalStatus === "blank") {
        setArmedRows((m)=>Object.assign({}, m, { [row.id]: true }));
      }
      setSweep((s)=>Object.assign({}, s, { done:i+1, currentId:"" }));
    }
    setSweep((s)=>Object.assign({}, s, { running:false, currentId:"" }));
  }

  useEffect(()=>{
    let on = true;
    const tick = async ()=>{ if(on && !sweep.running) await refresh(date); };
    tick();
    const id = setInterval(tick, 30_000);
    return ()=>{ on = false; clearInterval(id); };
  },[date, sweep.running]);

  const lanes = [
    { id:"eligibility", label:"Eligibility", count: (W.kpis && W.kpis.eligibility) || 0 },
    { id:"priorAuth", label:"Prior Auth", count: (W.kpis && W.kpis.priorAuth) || 0 },
    { id:"coding", label:"Coding Ops", count: (W.kpis && W.kpis.coding) || 0 },
    { id:"exceptions", label:"Exceptions", count: (W.kpis && W.kpis.exceptions) || 0 },
  ];
  const queueMap = {
    eligibility: (W.queues && W.queues.eligibility) || [],
    priorAuth: (W.queues && W.queues.priorAuth) || [],
    coding: (W.queues && W.queues.coding) || [],
    exceptions: (W.queues && W.queues.exceptions) || [],
  };
  let rows = queueMap[lane] || [];
  if (reasonFilter !== "all") rows = rows.filter((r)=>String(r.reasonCode||"")===reasonFilter);
  if (ownerFilter !== "all") rows = rows.filter((r)=>String(r.owner||"")===ownerFilter);
  if (statusFilter !== "all") rows = rows.filter((r)=>String(r.status||"")===statusFilter);
  const reasons = Array.from(new Set((queueMap[lane]||[]).map((r)=>r.reasonCode).filter(Boolean)));
  const owners = Array.from(new Set((queueMap[lane]||[]).map((r)=>r.owner).filter(Boolean)));
  const statuses = Array.from(new Set((queueMap[lane]||[]).map((r)=>r.status).filter(Boolean)));

  // Live tallies from the dry-propose sweep (eligibility lane) — feeds the
  // Source Verification strip so the trust anchor ticks as the agent works.
  const sweepTally = (lane === "eligibility")
    ? rows.reduce((acc, r)=>{
        const st = wfSweepState(pipelineRuns[r.id]);
        if (st === "signed") acc.signed += 1;
        else if (st === "craig") acc.craig += 1;
        else if (st === "active") acc.active += 1;
        else if (st === "error") acc.error += 1;
        if (armedRows[r.id]) acc.armed += 1;
        return acc;
      }, { signed:0, craig:0, active:0, error:0, armed:0 })
    : null;
  const eligibilityRunnable = (queueMap.eligibility||[]).filter((r)=>r.patientRef).length;

  return (
    <div className="module">
      <div className="hero-grid" style={{ marginBottom: 14 }}>
        <WfKpi label="Eligibility queue" value={(W.kpis && W.kpis.eligibility) || 0} tone="" />
        <WfKpi label="Prior auth queue" value={(W.kpis && W.kpis.priorAuth) || 0} tone="gilt" />
        <WfKpi label="Coding queue" value={(W.kpis && W.kpis.coding) || 0} tone="" />
        <WfKpi label="Exceptions" value={(W.kpis && W.kpis.exceptions) || 0} tone="deny" />
      </div>

      <div style={{ display:"flex", gap:8, margin:"0 0 12px", flexWrap:"wrap" }}>
        {lanes.map((l)=>(
          <button
            key={l.id}
            className={"pill-btn " + (lane===l.id ? "on" : "")}
            onClick={()=>setLane(l.id)}
            style={{ cursor:"pointer" }}
          >
            {l.label}
            <span style={{ marginLeft:6, opacity:.72 }}>{l.count}</span>
          </button>
        ))}
      </div>

      <div style={{ display:"flex", gap:8, margin:"0 0 12px", flexWrap:"wrap", alignItems:"center" }}>
        <button
          className="pill-btn"
          onClick={()=>{
            const d = new Date(date+"T12:00:00");
            d.setDate(d.getDate()-1);
            const n = `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,"0")}-${String(d.getDate()).padStart(2,"0")}`;
            setDate(n);
            refresh(n);
          }}
        >
          ◀ Prev
        </button>
        <input
          type="date"
          value={date}
          onChange={(e)=>{ setDate(e.target.value); refresh(e.target.value); }}
          style={{ fontFamily:"var(--fm)", fontSize:11, border:"1px solid var(--canvas-dark)", borderRadius:7, padding:"7px 8px", background:"#fff" }}
        />
        <button
          className="pill-btn"
          onClick={()=>{
            const d = new Date(date+"T12:00:00");
            d.setDate(d.getDate()+1);
            const n = `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,"0")}-${String(d.getDate()).padStart(2,"0")}`;
            setDate(n);
            refresh(n);
          }}
        >
          Next ▶
        </button>
        <button className="pill-btn" onClick={()=>{ const t=isoToday(); setDate(t); refresh(t); }}>Today</button>
        <select value={reasonFilter} onChange={(e)=>setReasonFilter(e.target.value)} style={{ fontFamily:"var(--fm)", fontSize:11, border:"1px solid var(--canvas-dark)", borderRadius:7, padding:"7px 8px", background:"#fff" }}>
          <option value="all">reason: all</option>
          {reasons.map((r)=><option key={r} value={r}>{r}</option>)}
        </select>
        <select value={ownerFilter} onChange={(e)=>setOwnerFilter(e.target.value)} style={{ fontFamily:"var(--fm)", fontSize:11, border:"1px solid var(--canvas-dark)", borderRadius:7, padding:"7px 8px", background:"#fff" }}>
          <option value="all">owner: all</option>
          {owners.map((o)=><option key={o} value={o}>{o}</option>)}
        </select>
        <select value={statusFilter} onChange={(e)=>setStatusFilter(e.target.value)} style={{ fontFamily:"var(--fm)", fontSize:11, border:"1px solid var(--canvas-dark)", borderRadius:7, padding:"7px 8px", background:"#fff" }}>
          <option value="all">status: all</option>
          {statuses.map((s)=><option key={s} value={s}>{s}</option>)}
        </select>
        <button className="pill-btn" onClick={()=>{ setReasonFilter("all"); setOwnerFilter("all"); setStatusFilter("all"); }}>Clear filters</button>
        <button className="pill-btn" onClick={()=>refresh(date)}>Refresh</button>
        <button className="pill-btn" onClick={runBenchmark}>Benchmark 10</button>
        {controls.phase1AReadOnly!==false && (
          <span style={{ fontFamily:"var(--fm)", fontSize:10.5, color:"#3a5f4a", letterSpacing:".04em" }}>PHASE 1A READ-ONLY</span>
        )}
        {controls.externalWritesEnabled===false && (
          <span style={{ fontFamily:"var(--fm)", fontSize:10.5, color:"#3a5f4a", letterSpacing:".04em" }}>NO DRCHRONO WRITEBACK</span>
        )}
        {controls.writebackEnabled===false && (
          <span style={{ fontFamily:"var(--fm)", fontSize:10.5, color:"#9A2A2A", letterSpacing:".04em" }}>OPAGENT QUEUE UPDATES DISABLED</span>
        )}
        <span style={{ marginLeft:"auto", fontFamily:"var(--fm)", fontSize:10.5, color:"var(--ink-faint)", letterSpacing:".04em" }}>
          updated {W.generatedAt ? new Date(W.generatedAt).toLocaleTimeString([], { hour:"2-digit", minute:"2-digit" }) : "—"}
        </span>
      </div>

      <div style={{ margin:"0 0 12px", border:"1px solid var(--canvas-dark)", borderRadius:10, padding:"10px 12px", background:"#fff" }}>
        <div style={{ fontFamily:"var(--fm)", fontSize:10.5, letterSpacing:".06em", textTransform:"uppercase", color:"var(--ink-soft)" }}>
          Source Verification · DrChrono migration check
        </div>
        <div style={{ marginTop:6, fontFamily:"var(--fs)", fontSize:13, color:"var(--ink)" }}>
          Day <b>{dayTxt || date}</b> · source <b>{meta.source || "drchrono_schedule"}</b> · schedule rows <b>{meta.scheduleRows ?? "—"}</b> · eligibility rows <b>{meta.eligibilityRows ?? "—"}</b>
          {rowsMismatch && <span style={{ color:"#9A2A2A", marginLeft:8, fontWeight:700 }}>COUNT MISMATCH — investigate mapping</span>}
        </div>
        <div style={{ marginTop:6, fontFamily:"var(--fm)", fontSize:10.5, color:"var(--ink-faint)", letterSpacing:".04em", textTransform:"uppercase", display:"flex", gap:12, flexWrap:"wrap" }}>
          <span>missing template {reasonCounts.missingTemplate || 0}</span>
          <span>identity mismatch {reasonCounts.identityMismatch || 0}</span>
          <span>manual review {reasonCounts.manualReview || 0}</span>
          <span>pending Craig {reasonCounts.pendingCraig || 0}</span>
        </div>
        {sweepTally && (sweepTally.signed || sweepTally.craig || sweepTally.active || sweep.running || sweepTally.armed) ? (
          <div className="wf-sv-live">
            <span className="wf-sv-chip active">signed / ready <b>{sweepTally.signed}</b></span>
            <span className="wf-sv-chip pending">pending Craig <b>{sweepTally.craig}</b></span>
            {sweepTally.active ? <span className="wf-sv-chip"><b>{sweepTally.active}</b> running</span> : null}
            <span className="wf-sv-chip">armed <b>{sweepTally.armed}</b></span>
            {sweep.running && <span className="wf-sv-chip">swept <b>{sweep.done}/{sweep.total}</b></span>}
            {sweepTally.error ? <span className="wf-sv-chip"><b>{sweepTally.error}</b> error</span> : null}
          </div>
        ) : null}
        {!!(meta.appointmentIdsSample && meta.appointmentIdsSample.length) && (
          <div style={{ marginTop:6, fontFamily:"var(--fm)", fontSize:10.5, color:"var(--ink-faint)", letterSpacing:".03em" }}>
            sample appt IDs: {meta.appointmentIdsSample.join(", ")}
          </div>
        )}
      </div>
      {bench && (
        <div style={{ margin:"0 0 12px", border:"1px solid var(--canvas-dark)", borderRadius:10, padding:"10px 12px", background:"#fff" }}>
          <div style={{ fontFamily:"var(--fm)", fontSize:10.5, letterSpacing:".06em", textTransform:"uppercase", color:"var(--ink-soft)" }}>
            Eligibility Benchmark (sample {bench.sampled}, dry-run)
          </div>
          <div style={{ marginTop:6, fontFamily:"var(--fs)", fontSize:13, color:"var(--ink)" }}>
            active <b>{bench.metrics && bench.metrics.active}</b> · inactive/unclear <b>{bench.metrics && bench.metrics.inactive}</b> · no data <b>{bench.metrics && bench.metrics.noData}</b> · avg latency <b>{bench.metrics && bench.metrics.avgElapsedMs}ms</b>
          </div>
        </div>
      )}

      {lane === "eligibility" && (
        <div className="wf-sweep">
          <button
            className="wf-sweep-go"
            disabled={sweep.running || !rows.length}
            onClick={()=>runSweep(rows)}
          >
            {sweep.running && <span className="wf-mini-spinner" aria-hidden="true" style={{ borderTopColor:"#0D2B1E" }}></span>}
            {sweep.running ? `Running queue… ${sweep.done}/${sweep.total}` : "Run eligibility queue"}
          </button>
          <div className="wf-sweep-meta">
            <div className="wf-sweep-title">Work the whole queue — one click</div>
            <div className="wf-sweep-sub">
              {rows.length} row{rows.length===1?"":"s"} in view{eligibilityRunnable !== rows.length ? ` · ${eligibilityRunnable} runnable in lane` : ""} · dry-propose, nothing is written
            </div>
          </div>
          <span className="wf-dry-pill">Dry-propose default</span>
          <label className="wf-sweep-toggle" title="When ON, clean rows are auto-armed as the sweep resolves them. Writes still require server writeback to be enabled.">
            <input type="checkbox" checked={armAllClean} onChange={(e)=>setArmAllClean(e.target.checked)} disabled={sweep.running} />
            Arm all clean rows
          </label>
        </div>
      )}

      <div style={{ display:"grid", gap:8 }}>
        {!rows.length && (
          <div style={{ padding:"18px 14px", border:"1px dashed rgba(22,61,43,.20)", borderRadius:10, fontFamily:"var(--fs)", fontSize:13, color:"var(--ink-faint)" }}>
            No items in this lane yet.
          </div>
        )}
        {rows.map((r)=>(
          <WfRow
            key={r.id} row={r} lane={lane} busy={busyId===r.id}
            eligibilityRun={eligibilityRuns[r.id]} demographicsRun={demographicsRuns[r.id]}
            pipelineRun={pipelineRuns[r.id]} armed={!!armedRows[r.id]} isExpanded={!!expandedRows[r.id]}
            sweepState={wfSweepState(pipelineRuns[r.id])}
            onUpdate={updateItem} onRunEligibility={runEligibility} onRunDemographics={runDemographics}
            onRunPipeline={runPipeline} onArm={toggleArm} onToggleEvidence={toggleEvidence}
          />
        ))}
      </div>
    </div>
  );
}

