// screens/pipeline.jsx — patient pipeline timeline (12 nodes)

function ScreenPipeline({ role, scenario, patientId, onOpenPatient, onRoleClick }) {
  const [selected, setSelected] = useState(patientId || 'zhang');
  const p = PATIENTS[selected];

  return (
    <div>
      <TopBar role={role} onRoleClick={onRoleClick} title="患者流水线" subtitle="全科共享 · 患者维度进度视图" />

      {/* Patient pill switcher */}
      <div style={{ padding: '4px 16px 12px', display:'flex', gap: 8, overflowX: 'auto' }}>
        {ALL_PATIENTS.map(pid => {
          const pp = PATIENTS[pid];
          const active = selected === pid;
          return (
            <button key={pid} onClick={() => setSelected(pid)} style={{
              flexShrink: 0,
              display:'inline-flex', alignItems:'center', gap: 8,
              padding: '6px 12px 6px 6px', borderRadius: 999,
              background: active ? 'var(--brand-ink)' : '#fff',
              color: active ? '#fff' : 'var(--t1)',
              border: active ? '1px solid var(--brand-ink)' : '1px solid var(--border)',
              fontSize: 13, fontWeight: 500, cursor: 'pointer',
            }}>
              <span style={{
                width: 22, height: 22, borderRadius: 22,
                background: active ? 'rgba(255,255,255,0.22)' : 'var(--brand-soft)',
                color: active ? '#fff' : 'var(--brand)',
                display:'inline-flex', alignItems:'center', justifyContent:'center',
                fontFamily: "'IBM Plex Mono', monospace",
                fontSize: 10, fontWeight: 600,
              }}>{pp.photoTag}</span>
              {pp.name}
            </button>
          );
        })}
      </div>

      {/* Patient identity card */}
      <div style={{ padding: '0 16px' }}>
        <Card pad={0}>
          <div style={{ padding: '14px 16px' }}>
            <div style={{ display:'flex', alignItems:'flex-start', gap: 12 }}>
              <PatientSigil tag={p.photoTag} size={44} />
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ display:'flex', alignItems:'baseline', gap: 8 }}>
                  <div style={{ fontSize: 19, fontWeight: 700, color:'var(--t1)', letterSpacing: -0.3 }}>{p.name}</div>
                  <div style={{ fontSize: 12, color:'var(--t3)' }}>{p.sex} · {p.age}岁</div>
                  <div style={{ marginLeft:'auto', fontSize: 11 }} className="mono" >{p.id}</div>
                </div>
                <div style={{ fontSize: 13, color:'var(--t2)', marginTop: 3 }}>{p.dx}</div>
              </div>
            </div>

            <div style={{
              marginTop: 12, padding: '10px 12px',
              background: 'var(--surface-2)', borderRadius: 9,
              border: '1px solid var(--border-soft)',
              display:'grid', gridTemplateColumns: '1fr 1fr', gap: 6,
            }}>
              <KV label="处方" value={p.rx} />
              <KV label="部位" value={p.site} />
              <KV label="机器" value={p.machine} />
              <KV label="始期" value={p.startDate} mono />
            </div>
          </div>
        </Card>
      </div>

      {/* Timeline */}
      <SectionLabel right="12 节点">放疗流水线</SectionLabel>
      <div style={{ padding: '0 16px' }}>
        <Card pad={0}>
          <div style={{ padding: '16px 14px 4px' }}>
            <NodeStripV2 patient={p} />
          </div>
          <div style={{ borderTop: '1px solid var(--border-soft)', padding: '0' }}>
            {NODES.map((n, i) => (
              <NodeRow key={n.id} node={n} pn={p.progress[n.id]} last={i === NODES.length-1} />
            ))}
          </div>
        </Card>
      </div>

      {/* Cross-system aggregation */}
      <SectionLabel right="只读 · 来自 TPS/RVS">关联数据</SectionLabel>
      <div style={{ padding: '0 16px', display:'flex', flexDirection:'column', gap: 10 }}>
        <DVHSummary patient={p} />
        <PlanInfo patient={p} />
      </div>

      <div style={{ height: 110 }}/>
    </div>
  );
}

// Larger, more readable node strip
function NodeStripV2({ patient }) {
  // Find current = first non-done
  const cur = NODES.find(n => patient.progress[n.id]?.state !== 'done')?.id;
  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'flex-start', gap: 0 }}>
        {NODES.map((n, i) => {
          const p = patient.progress[n.id] || { state: 'pending' };
          return (
            <React.Fragment key={n.id}>
              <NodeBead state={p.state} label={n.short} k={n.k} current={cur === n.id} />
              {i < NODES.length - 1 && <BeadLine state={p.state} />}
            </React.Fragment>
          );
        })}
      </div>
    </div>
  );
}

// Single node row in the expanded timeline list
function NodeRow({ node, pn, last }) {
  const state = pn?.state || 'pending';
  const tagMap = {
    done: { kind: 'done', label: '已完成' },
    active: { kind: 'active', label: '进行中' },
    mine: { kind: 'mine', label: '等我' },
    blocked: { kind: 'blocked', label: '驳回' },
    pending: { kind: 'pending', label: '未启动' },
  };
  const t = tagMap[state];

  return (
    <div style={{
      padding: '12px 16px',
      borderBottom: last ? 'none' : '1px solid var(--border-soft)',
      display: 'flex', gap: 12, alignItems: 'flex-start',
    }}>
      <div style={{
        width: 28, height: 28, borderRadius: 14,
        background: state==='done' ? 'var(--brand-soft)' : 'var(--bg-2)',
        color: state==='done' ? 'var(--brand)' : 'var(--t3)',
        display:'flex', alignItems:'center', justifyContent:'center',
        fontFamily: "'IBM Plex Mono', monospace", fontSize: 12, fontWeight: 700,
        flexShrink: 0,
      }}>{String(node.k).padStart(2,'0')}</div>

      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ display:'flex', alignItems:'center', gap: 8 }}>
          <div style={{ fontSize: 14, fontWeight: 600, color:'var(--t1)' }}>{node.label}</div>
          <Chip kind={t.kind}>{t.label}</Chip>
        </div>
        <div style={{ marginTop: 4, fontSize: 12, color:'var(--t2)', display:'flex', gap: 12, flexWrap:'wrap' }}>
          {pn?.by && <span>{ROLES[pn.by.role]?.name} {pn.by.name}</span>}
          {pn?.at && <span className="mono">{pn.at}</span>}
          {pn?.fraction && <span>分次 <span className="mono">{pn.fraction}</span></span>}
          {pn?.gamma && <span>Gamma <span className="mono">{pn.gamma}</span></span>}
          {pn?.signed && <span style={{ color:'var(--st-done-ink)' }}><I.Lock size={10}/> 电子签名</span>}
          {pn?.waiting && <span><I.Clock size={10}/> 等待 <span className="mono">{pn.waiting}</span></span>}
          {pn?.tag && <span style={{ color:'var(--st-block-ink)', fontWeight:500 }}>{pn.tag}</span>}
        </div>
      </div>

      {(state === 'mine' || state === 'blocked') && (
        <button style={{
          background: state==='mine'?'var(--brand)':'#B14B0E',
          color: '#fff', border: 'none',
          fontSize: 12, fontWeight: 600, padding: '6px 10px',
          borderRadius: 8, cursor: 'pointer', flexShrink: 0,
        }}>处理</button>
      )}
    </div>
  );
}

// DVH summary card — fakes pulling from TPS
function DVHSummary({ patient }) {
  // mock per-patient
  const data = {
    zhang: [
      { name: 'PTV-高危', target: '≥ 95% 处方剂量', value: '97.2%', ok: true, kind: '靶区' },
      { name: 'PTV-低危', target: '≥ 95% 处方剂量', value: '96.8%', ok: true, kind: '靶区' },
      { name: '脊髓 Spinal cord', target: 'Dmax ≤ 45 Gy', value: '43.8 Gy', ok: true, kind: 'OAR' },
      { name: '腮腺 Parotid R', target: 'Dmean ≤ 26 Gy', value: '25.4 Gy', ok: true, kind: 'OAR' },
      { name: '腮腺 Parotid L', target: 'Dmean ≤ 26 Gy', value: '27.1 Gy', ok: false, kind: 'OAR' },
    ],
    li: [
      { name: 'PTV', target: '≥ 95% 处方剂量', value: '96.4%', ok: true, kind: '靶区' },
      { name: '肺 Lung-PTV', target: 'V20 ≤ 35%', value: '32%', ok: true, kind: 'OAR' },
      { name: '心脏 Heart', target: 'Dmean ≤ 26 Gy', value: '18.2 Gy', ok: true, kind: 'OAR' },
      { name: '脊髓 Spinal cord', target: 'Dmax ≤ 45 Gy', value: '38.0 Gy', ok: true, kind: 'OAR' },
    ],
    wang: [
      { name: 'PTV', target: '≥ 95% 处方剂量', value: '92.3%', ok: false, kind: '靶区' },
      { name: '心脏 Heart', target: 'Dmean ≤ 4 Gy', value: '3.8 Gy', ok: true, kind: 'OAR' },
      { name: '同侧肺 Lung', target: 'V20 ≤ 20%', value: '17%', ok: true, kind: 'OAR' },
    ],
  };
  const rows = data[Object.keys(PATIENTS).find(k => PATIENTS[k] === patient)] || [];

  return (
    <Card pad={0}>
      <div style={{
        padding: '12px 14px 8px',
        display:'flex', alignItems:'center', justifyContent:'space-between',
        borderBottom: '1px solid var(--border-soft)',
      }}>
        <div>
          <div style={{ fontSize: 14, fontWeight: 600 }}>DVH 达标摘要</div>
          <div style={{ fontSize: 11, color: 'var(--t3)', marginTop: 2 }}>聚合自 TPS · 决策驾驶舱视图</div>
        </div>
        <button style={{
          fontSize: 11, color: 'var(--brand)', background: 'transparent',
          border: 'none', cursor: 'pointer', display:'inline-flex', alignItems:'center', gap: 4, padding: 0,
        }}>
          在 TPS 打开 <I.External size={11}/>
        </button>
      </div>
      <div style={{ padding: '4px 0' }}>
        {rows.map((r, i) => (
          <div key={i} style={{
            padding: '9px 14px',
            display:'flex', alignItems:'center', gap: 10,
            borderBottom: i < rows.length-1 ? '1px solid var(--border-soft)' : 'none',
          }}>
            <span style={{
              fontSize: 9.5, fontWeight: 600,
              padding: '2px 5px', borderRadius: 4,
              background: r.kind==='靶区' ? '#EAF2FB' : '#FFF7E6',
              color: r.kind==='靶区' ? '#1F5AA8' : '#A66700',
              letterSpacing: 0.2,
            }}>{r.kind}</span>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 13, fontWeight: 500, color:'var(--t1)' }}>{r.name}</div>
              <div style={{ fontSize: 11, color: 'var(--t3)' }}>{r.target}</div>
            </div>
            <span className="mono" style={{
              fontSize: 13, fontWeight: 600,
              color: r.ok ? 'var(--st-done-ink)' : 'var(--st-block-ink)',
            }}>{r.value}</span>
            <span style={{
              width: 18, height: 18, borderRadius: 18,
              background: r.ok ? 'var(--st-done-bg)' : 'var(--st-block-bg)',
              color: r.ok ? 'var(--st-done-ink)' : 'var(--st-block-ink)',
              display:'flex', alignItems:'center', justifyContent:'center',
            }}>
              {r.ok ? <I.Check size={11}/> : <I.X size={10}/>}
            </span>
          </div>
        ))}
      </div>
    </Card>
  );
}

// Plan info card — short
function PlanInfo({ patient }) {
  return (
    <Card pad={0}>
      <div style={{
        padding: '12px 14px 8px',
        display:'flex', alignItems:'center', justifyContent:'space-between',
        borderBottom: '1px solid var(--border-soft)',
      }}>
        <div>
          <div style={{ fontSize: 14, fontWeight: 600 }}>计划与处方</div>
          <div style={{ fontSize: 11, color: 'var(--t3)', marginTop: 2 }}>聚合自 OIS · 当前生效版本</div>
        </div>
        <Chip kind="brand">v2 · VMAT</Chip>
      </div>
      <div style={{ padding: '12px 14px', display:'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
        <KV label="处方" value={patient.rx} />
        <KV label="技术" value="VMAT · 6MV" />
        <KV label="束流" value="2 弧" />
        <KV label="MU" value={<span className="mono">688</span>} />
        <KV label="冷冻签名" value={<span style={{color:'var(--st-done-ink)'}}>已签 · 陈雯</span>} />
        <KV label="提交" value="王思雨 · 05-14" />
      </div>
    </Card>
  );
}

Object.assign(window, { ScreenPipeline });
