/* ThemeDiffPage.jsx — "Theme comparison / 主题对比".
   Proves how little differs across themes, makes each divergence legible + judgeable, captures a
   per-divergence rationale (routed through Changes), and ships a projector-clean Present mode. */
const { useState: useStateTM, useEffect: useEffectTM } = React;

function tmStatusMeta(s) {
  return ({
    intentional: { en:'Intentional', zh:'合理',   tone:'success' },
    review:      { en:'Needs review',zh:'待复核', tone:'warning' },
    fix:         { en:'To fix',      zh:'需修复', tone:'danger'  },
  })[s] || null;
}

function ThemeDiffPage({ ctx, theme, rev, rationaleMap, onSaveRationale, focus, clearFocus, onBack }) {
  const [cmode, setCmode] = useStateTM((ctx && ctx.mode) || 'light');
  const [baseline, setBaseline] = useStateTM((ctx && ctx.theme && ctx.theme.id) || (THEMES[0] && THEMES[0].id));
  const [statusF, setStatusF] = useStateTM('all');
  const [view, setView] = useStateTM('compare');
  const [sel, setSel] = useStateTM(null);          // token id open in the drawer
  const [presentIdx, setPresentIdx] = useStateTM(0);
  const rmap = rationaleMap || {};
  const rk = (id) => id + '@' + cmode;

  React.useEffect(() => { if (focus && focus.tokenId) { setCmode(focus.mode||'light'); setSel(focus.tokenId); if (clearFocus) clearFocus(); } }, [focus]);

  /* LIVE recompute: re-derived every render. `rev` (bumped by app on every token/theme edit)
     is a prop, so any data edit re-renders this component and the lines below recompute from the
     current TOKEN_MAP/THEMES. cmode/baseline are local state, so they re-render too. */
  void rev;
  const variantIds = themeVariantTokenIds();
  const allRows = variantIds.map(id => divergenceRow(id, cmode, baseline)).sort((a,b)=>b.maxDE-a.maxDE);
  const total = (typeof TOKENS!=='undefined'?TOKENS:[]).length;
  const diffN = variantIds.length, sameN = total - diffN;
  const samePct = Math.round(sameN/(total||1)*100);

  const rowStatus = (id) => { const r = rmap[rk(id)]; return r && r.reason ? (r.status||'review') : 'unexplained'; };
  const rows = allRows.filter(r => statusF==='all' || rowStatus(r.tokenId)===statusF);

  /* ---- Present mode keyboard nav ---- */
  useEffectTM(() => {
    if (view !== 'present') return;
    const onKey = (e) => {
      if (e.key === 'Escape') setView('compare');
      else if (e.key === 'ArrowRight') setPresentIdx(i => Math.min(allRows.length, i+1));
      else if (e.key === 'ArrowLeft') setPresentIdx(i => Math.max(0, i-1));
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [view, allRows.length]);

  const themesArr = typeof THEMES!=='undefined'?THEMES:[];
  const baseTheme = themesArr.find(t=>t.id===baseline) || themesArr[0];

  if (view === 'present') return <PresentMode rows={allRows} idx={presentIdx} setIdx={setPresentIdx} cmode={cmode} samePct={samePct} sameN={sameN} total={total} rmap={rmap} rk={rk} onExit={()=>setView('compare')} />;

  return (
    <div className="h-full flex flex-col bg-app">
      <PageToolbar title={tr('Theme comparison','主题对比')} count={diffN}
        subtitle={tr(`${sameN} of ${total} tokens are identical across all ${themesArr.length} themes · ${diffN} differ — all derive from the brand accent`,
                     `${total} 个 token 中有 ${sameN} 个在全部 ${themesArr.length} 个主题下完全一致 · ${diffN} 个不同 —— 均源自品牌强调色`)}
        leadingActions={<>
          {onBack && <><Button variant="ghost" size="sm" icon="arrowR" className="[&_svg]:rotate-180" onClick={onBack}>{tr('Themes','主题')}</Button><div className="w-px h-6 bg-line" /></>}
          <Segmented size="sm" value={cmode} onChange={setCmode} options={[{value:'light',label:tr('Light','浅'),icon:'sun'},{value:'dark',label:tr('Dark','深'),icon:'moon'}]} />
          <div className="inline-flex items-center gap-1.5">
            <span className="text-[12px] text-ink3">{tr('Baseline','基准')}</span>
            <select value={baseline} onChange={e=>setBaseline(e.target.value)} className="h-7 bg-sunken border border-line rounded-[7px] px-2 text-[12.5px] text-ink focus-ring">
              {themesArr.map(t=> <option key={t.id} value={t.id}>{t.name}</option>)}
            </select>
          </div>
          <Segmented size="sm" value={statusF} onChange={setStatusF} options={[
            {value:'all',label:tr('All','全部')},{value:'review',label:tr('Review','待复核')},{value:'fix',label:tr('To fix','需修复')},{value:'unexplained',label:tr('No reason','缺说明')}]} />
        </>}
        facets={<Segmented size="sm" value={view} onChange={setView} options={[{value:'compare',label:tr('Compare','对比'),icon:'diff'},{value:'present',label:tr('Present','演示'),icon:'eye'}]} />} />

      <div className="flex-1 overflow-y-auto ds-scroll [scrollbar-gutter:stable]">
        <div className="max-w-[1080px] mx-auto px-6 py-5">

          {/* (A) hero proof strip — one Button, five brands */}
          <div className="grid grid-cols-2 md:grid-cols-5 gap-3 mb-7">
            {themesArr.map(t => (
              <div key={t.id} className={cx('rounded-[12px] border bg-panel p-3.5 flex flex-col gap-2.5', t.id===baseline?'border-accent ring-1 ring-[color:var(--accent)]':'border-line')}>
                <div><div className="text-[13px] font-semibold text-ink truncate">{t.name}</div><div className="text-[11px] text-ink3 truncate">{t.line||''}</div></div>
                <div className="flex gap-1">{[400,500,600].map(s=> <Swatch key={s} color={t.accent[s]} size={26} radius={6} />)}</div>
                <div style={{ '--accent':t.accent[500], '--accent-weak':'color-mix(in srgb,'+t.accent[500]+' 12%,transparent)', '--on-accent':onAccent(cmode) }}>
                  <Button variant="primary" size="sm" className="w-full justify-center">{tr('Primary','主按钮')}</Button>
                </div>
              </div>
            ))}
          </div>

          {/* (B) divergence matrix */}
          {rows.length===0 ? <EmptyState icon="check" title={tr('Nothing matches this filter','没有匹配项')} body={tr('Every divergence here is accounted for.','此筛选下没有需要关注的差异。')} /> : (
          <div className="rounded-[12px] border border-line bg-panel overflow-hidden">
            <div className="overflow-x-auto ds-scroll">
              <table className="w-full border-collapse text-[12.5px]">
                <thead><tr className="bg-sunken border-b border-line text-left">
                  <th className="px-4 h-9 font-medium text-[11px] uppercase tracking-wide text-ink3 sticky left-0 bg-sunken z-[1]">Token</th>
                  {themesArr.map(t=> <th key={t.id} className={cx('px-3 h-9 font-medium text-[11px] tracking-wide text-ink3 whitespace-nowrap', t.id===baseline&&'border-l-2 border-[color:var(--accent)]')}>{t.name}{t.id===baseline && <span className="text-accent"> ·{tr(' base','基')}</span>}</th>)}
                  <th className="px-3 h-9 font-medium text-[11px] uppercase tracking-wide text-ink3 whitespace-nowrap">{tr('Magnitude','差异幅度')}</th>
                  <th className="px-3 h-9"></th>
                </tr></thead>
                <tbody>
                  {rows.map(r => {
                    const rr = rmap[rk(r.tokenId)];
                    const band = deltaBand(r.maxDE);
                    const sm = rr && rr.reason ? tmStatusMeta(rr.status) : null;
                    return (
                    <tr key={r.tokenId} onClick={()=>setSel(r.tokenId)} className={cx('border-b border-[color:var(--border)] last:border-0 hover:bg-hover transition cursor-pointer align-top', r.maxDE<1&&'opacity-60')}>
                      <td className="px-4 py-2.5 sticky left-0 bg-panel">
                        <div className="text-ink font-medium">{r.role}</div>
                        <div className="font-mono text-[11px] text-ink3 truncate">{r.tokenId}</div>
                      </td>
                      {r.cells.map(c => {
                        const aaFail = c.aaOnAccent != null && c.aaOnAccent < 4.5;
                        return (
                          <td key={c.themeId} className={cx('px-3 py-2.5 whitespace-nowrap', c.isBaseline&&'border-l-2 border-[color:var(--accent)]')}>
                            <div className="flex items-center gap-1.5"><Swatch color={c.value} size={20} radius={5} /><span className="font-mono text-[11px] text-ink2">{c.value}</span></div>
                            <div className="flex flex-wrap items-center gap-1 mt-1">
                              {c.pinned && <Pill tone="accent" icon="branch">{tr('pinned','已固定')}</Pill>}
                              {c.stale && <Pill tone="warning" icon="warningTri">{tr('base changed','基座已变')}</Pill>}
                              {aaFail && <Pill tone="danger">{tr('label <AA','文字未达 AA')}</Pill>}
                            </div>
                          </td>
                        );
                      })}
                      <td className="px-3 py-2.5 whitespace-nowrap"><Pill color={band.color}>ΔE {r.maxDE} · {tr(band.en,band.zh)}</Pill></td>
                      <td className="px-3 py-2.5 whitespace-nowrap text-right" onClick={e=>{e.stopPropagation(); setSel(r.tokenId);}}>
                        {sm ? <span className="inline-flex items-center gap-1.5"><Pill tone={sm.tone}>{tr(sm.en,sm.zh)}</Pill></span>
                          : <Button variant="ghost" size="sm" icon="edit">{tr('Add reason','补充说明')}</Button>}
                      </td>
                    </tr>
                  );})}
                </tbody>
              </table>
            </div>
          </div>)}

          {/* (C) sameness disclosure */}
          <SamenessDisclosure variantIds={variantIds} total={total} sameN={sameN} />
        </div>
      </div>

      {sel && <RationaleDrawer tokenId={sel} cmode={cmode} baseline={baseline} rmap={rmap} rk={rk} onClose={()=>setSel(null)} onSave={onSaveRationale} />}
    </div>
  );
}

/* collapsible list of the provably-identical tokens */
function SamenessDisclosure({ variantIds, total, sameN }) {
  const [open, setOpen] = useStateTM(false);
  const sameIds = (typeof TOKENS!=='undefined'?TOKENS:[]).map(t=>t.id).filter(id=>!variantIds.includes(id));
  return (
    <div className="mt-5">
      <button onClick={()=>setOpen(o=>!o)} className="inline-flex items-center gap-1.5 text-[12.5px] text-ink2 hover:text-ink transition">
        <Icon name={open?'chevronD':'chevronR'} size={14} />{tr(`${sameN} tokens are identical across every theme`,`${sameN} 个 token 在所有主题下完全一致`)}
      </button>
      {open && <div className="mt-2.5 flex flex-wrap gap-1.5">{sameIds.map(id=> <span key={id} className="font-mono text-[11px] text-ink3 bg-sunken border border-line rounded-[4px] px-1.5 py-0.5">{id}</span>)}</div>}
    </div>
  );
}

/* annotate-rationale drawer: see → judge → record reason, all in one surface */
function RationaleDrawer({ tokenId, cmode, baseline, rmap, rk, onClose, onSave }) {
  const r = divergenceRow(tokenId, cmode, baseline);
  const existing = rmap[rk(tokenId)];
  const [reason, setReason] = useStateTM(existing && existing.reason ? existing.reason : tr('Follows the active brand accent {400,500,600} — divergence is by design.','跟随当前品牌强调色 {400,500,600} —— 差异为设计预期。'));
  const [status, setStatus] = useStateTM(existing ? (existing.status||'intentional') : 'intentional');
  const worst = [...r.cells].sort((a,b)=>b.maxDE-a.maxDE)[0] || r.cells.find(c=>!c.isBaseline) || r.cells[0];
  const baseCell = r.cells.find(c=>c.isBaseline) || r.cells[0];
  return (
    <Drawer open={true} onClose={onClose} width={460}>
      <div className="flex items-start justify-between px-5 pt-4 pb-3 border-b border-line">
        <div className="min-w-0"><div className="text-[11px] uppercase tracking-wide text-ink3 mb-1">{tr('Divergence','差异')}</div>
          <h2 className="text-[15px] font-semibold text-ink truncate">{r.role}</h2>
          <div className="font-mono text-[11px] text-ink3 truncate">{tokenId} · {cmode}</div></div>
        <IconButton name="close" title="Close" onClick={onClose} />
      </div>
      <div className="flex-1 overflow-y-auto ds-scroll p-5 flex flex-col gap-5">
        {/* the divergence, large */}
        <div className="grid grid-cols-5 gap-2">
          {r.cells.map(c=>(
            <div key={c.themeId} className="flex flex-col items-center gap-1.5 text-center">
              <Swatch color={c.value} size={40} radius={8} />
              <div className={cx('text-[11px] truncate w-full', c.isBaseline?'text-accent font-medium':'text-ink2')}>{c.themeName}</div>
              <div className="font-mono text-[10px] text-ink3">{c.value}</div>
              {!c.isBaseline && c.dE>=1 && <Pill color={deltaBand(c.dE).color}>ΔE {c.dE}</Pill>}
            </div>
          ))}
        </div>
        <div className="rounded-[10px] border border-line bg-sunken p-3">
          <div className="text-[11px] uppercase tracking-wide text-ink3 mb-1.5">{tr('Same role everywhere','角色一致')}</div>
          <RefChain chain={r.refChain} />
        </div>
        {worst && worst.aaOnAccent!=null && (
          <div className="text-[12px] text-ink2 flex items-center gap-2">
            {tr('Label contrast on fill','文字对比度')}: <span className="font-mono">{worst.aaOnAccent}:1</span>
            {worst.aaOnAccent<4.5 && <Pill tone="danger">{tr('below AA','未达 AA')}</Pill>}
          </div>
        )}
        <Field label={tr('Why is this different?','为什么不同?')}>
          <TextArea rows={3} value={reason} onChange={e=>setReason(e.target.value)} placeholder={tr('e.g. Forge runs a warmer orange for high-glare factory floors','例如:Forge 用更暖的橙色以适配高反光产线')} />
        </Field>
        <Field label={tr('Assessment','判定')}>
          <Segmented size="sm" value={status} onChange={setStatus} options={[
            {value:'intentional',label:tr('Intentional','合理')},{value:'review',label:tr('Needs review','待复核')},{value:'fix',label:tr('To fix','需修复')}]} />
        </Field>
        {status==='fix' && <p className="text-[12px] text-ink3">{tr('Will appear in Changes as a flagged divergence.','将作为标记差异出现在「变更」中。')}</p>}
        {existing && existing.lastEditedBy && <p className="text-[11.5px] text-ink3">{tr('Last edited by ','最近编辑 ')}{existing.lastEditedBy}</p>}
      </div>
      <div className="px-5 py-3 border-t border-line flex justify-end gap-2">
        <Button variant="ghost" onClick={onClose}>{tr('Cancel','取消')}</Button>
        <Button variant="primary" icon="check" disabled={!canEdit()} onClick={()=>{ onSave && onSave(tokenId, cmode, { reason:reason.trim(), status, baselineTheme:baseline, maxDE:r.maxDE }); onClose(); }}>{tr('Save','保存')}</Button>
      </div>
    </Drawer>
  );
}

/* projector-clean Present mode: slide 0 summary + one divergent token per slide */
function PresentMode({ rows, idx, setIdx, cmode, samePct, sameN, total, rmap, rk, onExit }) {
  const themesArr = typeof THEMES!=='undefined'?THEMES:[];
  const undocumented = rows.filter(r => !(rmap[rk(r.tokenId)] && rmap[rk(r.tokenId)].reason)).length;
  const isSummary = idx === 0;
  const r = !isSummary ? rows[idx-1] : null;
  const n = rows.length + 1;
  return (
    <div className="h-full flex flex-col bg-app">
      <div className="flex items-center justify-between px-6 h-12 border-b border-line bg-panel shrink-0">
        <span className="text-[13px] font-medium text-ink">{tr('Theme comparison · Present','主题对比 · 演示')}</span>
        <Button variant="ghost" size="sm" icon="close" onClick={onExit}>{tr('Exit','退出')}</Button>
      </div>
      <div className="flex-1 overflow-hidden flex items-center justify-center px-12">
        {isSummary ? (
          <div className="text-center max-w-[760px]">
            <div className="text-[64px] font-semibold text-ink tracking-tight leading-none tabular-nums">{samePct}%</div>
            <div className="text-[20px] text-ink mt-3">{tr(`of tokens are identical across all ${themesArr.length} themes`,`的 token 在全部 ${themesArr.length} 个主题下完全一致`)}</div>
            <div className="text-[15px] text-ink2 mt-2">{tr('Only the brand accent diverges — by design.','仅品牌强调色不同 —— 出于设计。')}</div>
            <div className="flex items-center justify-center gap-6 mt-9">
              {themesArr.map(t=>(
                <div key={t.id} className="flex flex-col items-center gap-2">
                  <span className="w-14 h-14 rounded-[14px] border border-line" style={{ background:t.accent[500] }} />
                  <span className="text-[12px] text-ink2">{t.name}</span>
                </div>
              ))}
            </div>
            {undocumented>0 && <div className="text-[13px] text-warning mt-8">{tr(`${undocumented} differences still need a reason`,`${undocumented} 项差异仍需说明`)}</div>}
          </div>
        ) : (
          <div className="text-center max-w-[860px] w-full">
            <div className="text-[28px] font-semibold text-ink tracking-tight">{r.role}</div>
            <div className="flex items-end justify-center gap-8 mt-10">
              {r.cells.map(c=>(
                <div key={c.themeId} className="flex flex-col items-center gap-3">
                  <span className="w-16 h-16 rounded-[16px] border border-line" style={{ background:c.value }} />
                  <span className="text-[13px] text-ink">{c.themeName}</span>
                  <span className="text-[11px] text-ink3">{(themesArr.find(t=>t.id===c.themeId)||{}).line||''}</span>
                  <span style={{ '--accent':c.value, '--on-accent':onAccent(cmode) }}><Button variant="primary" size="sm">{tr('Primary','主按钮')}</Button></span>
                </div>
              ))}
            </div>
            <div className="mt-10 text-[15px] text-ink2 max-w-[620px] mx-auto">
              {(() => { const rr = rmap[rk(r.tokenId)];
                return rr && rr.reason ? <span>“{rr.reason}”{tmStatusMeta(rr.status) && rr.status!=='intentional' && <span className="ml-2"><Pill tone={tmStatusMeta(rr.status).tone}>{tr(tmStatusMeta(rr.status).en,tmStatusMeta(rr.status).zh)}</Pill></span>}</span>
                  : <span className="text-ink3">{tr('Reason not yet documented','尚未记录原因')}</span>;
              })()}
            </div>
          </div>
        )}
      </div>
      {/* nav */}
      <div className="flex items-center justify-center gap-4 h-16 shrink-0">
        <IconButton name="chevronR" title="Prev" onClick={()=>setIdx(i=>Math.max(0,i-1))} className="rotate-180" />
        <div className="flex items-center gap-1.5">{Array.from({length:n}).map((_,i)=> <span key={i} className={cx('w-1.5 h-1.5 rounded-full transition', i===idx?'bg-accent':'bg-[color:var(--border-strong)]')} />)}</div>
        <IconButton name="chevronR" title="Next" onClick={()=>setIdx(i=>Math.min(n-1,i+1))} />
      </div>
    </div>
  );
}

Object.assign(window, { ThemeDiffPage });
