// ViG Command Center — General Database (filter, sort, table, drawer)
const { useState: useStateDB, useMemo: useMemoDB } = React;

function GeneralDrawer({ g, open, onClose, canEdit }) {
  const { isOwned, toggle, ownedByName } = useOwn();
  if (!g) return null;
  const owned = isOwned(g);
  const assists = CALC.bestAssistants(g, window.VIG.generals.filter(x => x.type === g.type), 4);
  const buffs = [
    { label: 'Attack buff', value: g.totAtk, color: '#dc2626' },
    { label: 'Defense buff', value: g.totDef, color: '#2563eb' },
    { label: 'Leadership buff', value: g.totLdr, color: '#16a34a' },
  ];
  const maxBuff = Math.max(...buffs.map(b => b.value));
  return (
    <Drawer open={open} onClose={onClose} title="General detail">
      {g && (
        <div className="p-5">
          <div className="flex items-center gap-3.5">
            <Avatar name={g.name} size={48} />
            <div className="min-w-0 flex-1">
              <div className="truncate text-[17px] font-semibold text-zinc-900 dark:text-white">{g.name}</div>
              <div className="mt-1 flex items-center gap-2"><TypeTag type={g.type} /><Pill tone="zinc">Rank #{g.rank}</Pill></div>
            </div>
          </div>

          <div className="mt-4 flex items-center justify-between rounded-lg border border-zinc-200 bg-zinc-50 px-3.5 py-3 dark:border-zinc-800 dark:bg-zinc-800/40">
            <div>
              <div className="text-[12px] font-medium text-zinc-500">Ownership</div>
              <div className="text-[13px] font-semibold text-zinc-900 dark:text-white">{owned ? 'In your roster' : 'Not owned'}</div>
            </div>
            <Toggle on={owned} disabled={!canEdit} onClick={() => toggle(g)} />
          </div>

          <div className="mt-5 grid grid-cols-2 gap-3">
            <div className="rounded-lg border border-zinc-200 p-3 dark:border-zinc-800">
              <div className="text-[11px] uppercase tracking-wide text-zinc-400">Power score</div>
              <div className="mt-1 flex items-baseline gap-1"><span className="text-[24px] font-semibold tabular-nums text-brand">{g.power}</span><span className="text-[12px] text-zinc-400">/ 100</span></div>
              <Progress value={g.power} className="mt-2" />
            </div>
            <div className="rounded-lg border border-zinc-200 p-3 dark:border-zinc-800">
              <div className="text-[11px] uppercase tracking-wide text-zinc-400">Skill buffs</div>
              <div className="mt-1.5 space-y-1 text-[12px] text-zinc-600 dark:text-zinc-300">
                <div className="flex justify-between"><span>ATK / DEF / HP</span><span className="font-medium tabular-nums">{g.atkPct}/{g.defPct}/{g.hpPct}%</span></div>
                <div className="flex justify-between"><span>March speed</span><span className="font-medium tabular-nums">{g.msPct}%</span></div>
              </div>
            </div>
          </div>

          <h4 className="mt-5 text-[12px] font-semibold uppercase tracking-wide text-zinc-400">Full-build buff totals</h4>
          <div className="mt-2 space-y-2.5">
            {buffs.map(b => (
              <div key={b.label}>
                <div className="mb-1 flex justify-between text-[12px]"><span className="text-zinc-500">{b.label}</span><span className="font-medium tabular-nums text-zinc-900 dark:text-white">{b.value}%</span></div>
                <div className="h-1.5 w-full overflow-hidden rounded-full bg-zinc-100 dark:bg-zinc-800"><div className="h-full rounded-full" style={{ width: (b.value / maxBuff * 100) + '%', background: b.color }}></div></div>
              </div>
            ))}
          </div>

          <h4 className="mt-5 text-[12px] font-semibold uppercase tracking-wide text-zinc-400">Covenant role</h4>
          <div className="mt-2 flex flex-wrap gap-1.5">
            {g.cov.mc && <Pill tone="brand">Main covenant</Pill>}
            {g.cov.c1 && <Pill tone="blue">Covenant I</Pill>}
            {g.cov.c2 && <Pill tone="blue">Covenant II</Pill>}
            {g.cov.c3 && <Pill tone="blue">Covenant III</Pill>}
            {!g.cov.mc && !g.cov.c1 && !g.cov.c2 && !g.cov.c3 && <span className="text-[12px] text-zinc-400">Not part of a covenant set</span>}
          </div>

          <h4 className="mt-5 text-[12px] font-semibold uppercase tracking-wide text-zinc-400">Best assistant pairings</h4>
          <div className="mt-2 space-y-1.5">
            {assists.map(({ g: a, score }) => (
              <div key={a.name} className="flex items-center gap-2.5 rounded-lg border border-zinc-100 px-3 py-2 dark:border-zinc-800">
                <Avatar name={a.name} size={26} />
                <span className="flex-1 truncate text-[13px] text-zinc-700 dark:text-zinc-200">{a.name}</span>
                <Pill tone={score >= 75 ? 'green' : 'zinc'}>{score}% sync</Pill>
              </div>
            ))}
          </div>
        </div>
      )}
    </Drawer>
  );
}

const SORTS = [
  { value: 'rank', label: 'Rank' },
  { value: 'power', label: 'Power' },
  { value: 'name', label: 'Name' },
  { value: 'totAtk', label: 'Attack' },
];

const ROLE_OPTS = ['Sub-City', 'Wall', 'Monster'];

function DatabasePage({ canEdit }) {
  const V = window.VIG;
  const { isOwned, toggle, setAll, reset, isOwnedName, toggleName, hasTroopRow } = useOwn();
  const [q, setQ] = useStateDB(() => LS.get('vig2_db_search', ''));
  React.useEffect(() => {
    const h = e => { setQ(e.detail || ''); setRole('all'); setType('All'); };
    window.addEventListener('vig-db-search', h);
    return () => window.removeEventListener('vig-db-search', h);
  }, []);
  const [type, setType] = useStateDB('All');
  const [ownFilter, setOwnFilter] = useStateDB('all'); // all|owned|missing
  const [covOnly, setCovOnly] = useStateDB(false);
  const [role, setRole] = useStateDB('all'); // all | Sub-City | Wall | Monster
  const [sort, setSort] = useStateDB('rank');
  const [asc, setAsc] = useStateDB(true);
  const [sel, setSel] = useStateDB(null);

  const roleRows = useMemoDB(() => {
    if (role === 'all') return [];
    const ql = q.trim().toLowerCase();
    return (V.roles[role] || []).filter(r => {
      if (ql && !r.name.toLowerCase().includes(ql)) return false;
      const owned = isOwnedName(r.name);
      if (ownFilter === 'owned' && !owned) return false;
      if (ownFilter === 'missing' && owned) return false;
      return true;
    });
  }, [role, q, ownFilter, isOwnedName]);

  const rows = useMemoDB(() => {
    const ql = q.trim().toLowerCase();
    let r = V.generals.filter(g => {
      if (type !== 'All' && g.type !== type) return false;
      if (ownFilter === 'owned' && !isOwned(g)) return false;
      if (ownFilter === 'missing' && isOwned(g)) return false;
      if (covOnly && !(g.cov.mc || g.cov.c1 || g.cov.c2 || g.cov.c3)) return false;
      if (ql && !g.name.toLowerCase().includes(ql)) return false;
      return true;
    });
    r = r.slice().sort((a, b) => {
      let d = sort === 'name' ? a.name.localeCompare(b.name) : a[sort] - b[sort];
      return asc ? d : -d;
    });
    return r;
  }, [q, type, ownFilter, covOnly, sort, asc, isOwned]);

  const setSortCol = (col) => { if (sort === col) setAsc(!asc); else { setSort(col); setAsc(col === 'rank' || col === 'name'); } };
  const ownedCount = rows.filter(isOwned).length;
  const [view, setView] = useStateDB(() => LS.get('vig2_db_view', 'grid'));
  React.useEffect(() => { LS.set('vig2_db_view', view); }, [view]);
  const TYPE_C = { Ground: '#2563eb', Mounted: '#dc2626', Ranged: '#16a34a', Siege: '#9333ea' };

  return (
    <div className="space-y-4">
      <div className="flex flex-wrap items-center gap-2.5">
        <SearchInput value={q} onChange={setQ} placeholder="Search generals…" className="w-full sm:w-72" />
        <Segmented options={['All', 'Ground', 'Mounted', 'Ranged', 'Siege', ...ROLE_OPTS]}
          value={role !== 'all' ? role : type}
          onChange={(v) => { if (ROLE_OPTS.includes(v)) { setRole(v); } else { setRole('all'); setType(v); } }} />
        <Segmented options={[{ value: 'all', label: 'All' }, { value: 'owned', label: 'Owned' }, { value: 'missing', label: 'Missing' }]} value={ownFilter} onChange={setOwnFilter} />
        {role === 'all' && (
          <button onClick={() => setCovOnly(!covOnly)} className={`inline-flex h-9 items-center gap-1.5 rounded-lg border px-3 text-[13px] font-medium transition-colors ${covOnly ? 'border-brand bg-brand/10 text-brand' : 'border-zinc-200 text-zinc-600 hover:bg-zinc-50 dark:border-zinc-700 dark:text-zinc-300 dark:hover:bg-zinc-800'}`}>
            <Icon name="link" size={14} />Covenant only
          </button>
        )}
        <div className="ml-auto flex items-center gap-2">
          {role === 'all' && (
            <div className="flex overflow-hidden rounded-lg border border-zinc-200 dark:border-zinc-700">
              <button onClick={() => setView('grid')} title="Gallery view" className={`flex h-9 w-9 items-center justify-center transition-colors ${view === 'grid' ? 'bg-brand text-white' : 'text-zinc-400 hover:bg-zinc-50 dark:hover:bg-zinc-800'}`}><Icon name="grid" size={15} /></button>
              <button onClick={() => setView('table')} title="Table view" className={`flex h-9 w-9 items-center justify-center transition-colors ${view === 'table' ? 'bg-brand text-white' : 'text-zinc-400 hover:bg-zinc-50 dark:hover:bg-zinc-800'}`}><Icon name="database" size={15} /></button>
            </div>
          )}
          {canEdit && role === 'all' && <Btn variant="ghost" size="sm" onClick={reset} title="Reset to spreadsheet defaults">Reset</Btn>}
          <span className="text-[12px] tabular-nums text-zinc-400">{role === 'all' ? `${ownedCount}/${rows.length} owned` : `${roleRows.length} generals`}</span>
        </div>
      </div>

      <Card className="overflow-hidden">
        <div className="overflow-x-auto">
          {role !== 'all' ? (
            <table className="w-full min-w-[640px] text-left text-[13px]">
              <thead>
                <tr className="border-b border-zinc-100 text-[11px] uppercase tracking-wide text-zinc-400 dark:border-zinc-800">
                  <th className="w-16 px-4 py-2.5 font-medium">Rank</th>
                  <th className="px-4 py-2.5 font-medium">General</th>
                  <th className="px-4 py-2.5 font-medium">Role</th>
                  <th className="px-4 py-2.5 font-medium">In roster</th>
                  <th className="px-4 py-2.5 text-right font-medium">Owned</th>
                </tr>
              </thead>
              <tbody className="divide-y divide-zinc-50 dark:divide-zinc-800/60">
                {roleRows.map(r => {
                  const owned = isOwnedName(r.name);
                  const inDB = hasTroopRow(r.name);
                  return (
                    <tr key={r.name} className={`transition-colors hover:bg-zinc-50 dark:hover:bg-zinc-800/40 ${owned ? '' : 'opacity-70'}`}>
                      <td className="px-4 py-2.5 tabular-nums text-zinc-400">#{r.rank}</td>
                      <td className="px-4 py-2.5"><div className="flex items-center gap-2.5"><Avatar name={r.name} size={28} /><span className="font-medium text-zinc-900 dark:text-white">{r.name}</span></div></td>
                      <td className="px-4 py-2.5"><TypeTag type={role} /></td>
                      <td className="px-4 py-2.5">{inDB ? <Pill tone="blue">Ranked general</Pill> : <span className="text-[12px] text-zinc-400">Role specialist</span>}</td>
                      <td className="px-4 py-2.5"><div className="flex justify-end"><Toggle on={owned} disabled={!canEdit} onClick={() => toggleName(r.name)} /></div></td>
                    </tr>
                  );
                })}
                {roleRows.length === 0 && <tr><td colSpan="5" className="py-12 text-center text-zinc-400">No generals match your filters.</td></tr>}
              </tbody>
            </table>
          ) : view === 'grid' ? (
          <div className="grid grid-cols-2 gap-3 p-3 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5">
            {rows.map(g => {
              const owned = isOwned(g);
              const c = TYPE_C[g.type] || '#71717a';
              const hasCov = g.cov.mc || g.cov.c1 || g.cov.c2 || g.cov.c3;
              return (
                <div key={g.name + g.type} onClick={() => setSel(g)}
                  className="group relative cursor-pointer overflow-hidden rounded-xl border bg-white transition-all hover:-translate-y-0.5 dark:bg-zinc-900"
                  style={{ borderColor: owned ? c + '66' : 'var(--ln,rgba(0,0,0,.08))', opacity: owned ? 1 : .62 }}>
                  <div className="h-1" style={{ background: c }}></div>
                  <div className="relative flex flex-col items-center px-3 pb-3 pt-4" style={{ background: `radial-gradient(120% 80% at 50% 0%, ${c}14, transparent 70%)` }}>
                    <span className="absolute left-2 top-2 text-[10px] font-bold tabular-nums text-zinc-400">#{g.rank}</span>
                    {owned && <span className="absolute right-2 top-2 flex h-4 w-4 items-center justify-center rounded-full" style={{ background: c }}><Icon name="check" size={10} className="text-white" stroke={3} /></span>}
                    <div className="flex h-14 w-14 items-center justify-center rounded-xl text-[20px] font-bold text-white" style={{ background: `linear-gradient(140deg, ${c}, ${c}bb)`, boxShadow: `0 6px 18px -6px ${c}99` }}>{g.name.replace(/[^A-Za-z0-9]/g, '').slice(0, 2).toUpperCase()}</div>
                    <div className="mt-2 line-clamp-1 text-center text-[13px] font-semibold text-zinc-900 dark:text-white">{g.name}</div>
                    <div className="mt-0.5 flex items-center gap-1.5 text-[10.5px] uppercase tracking-wide" style={{ color: c }}>{g.type}</div>
                    <div className="mt-2 flex w-full items-center justify-center gap-2 border-t pt-2 text-[10.5px] tabular-nums text-zinc-500 dark:border-zinc-800 dark:text-zinc-400" style={{ borderColor: 'rgba(120,120,130,.12)' }}>
                      <span title="Attack">⚔ {g.totAtk}%</span>
                      {hasCov && <span className="rounded bg-brand/10 px-1 font-semibold text-brand">COV</span>}
                    </div>
                  </div>
                  {canEdit && <button onClick={e => { e.stopPropagation(); toggle(g); }} className="absolute inset-x-0 bottom-0 translate-y-full bg-brand py-1.5 text-[11px] font-semibold uppercase tracking-wide text-white transition-transform group-hover:translate-y-0">{owned ? 'Owned ✓' : 'Mark owned'}</button>}
                </div>
              );
            })}
            {rows.length === 0 && <div className="col-span-full py-12 text-center text-zinc-400">No generals match your filters.</div>}
          </div>
          ) : (
          <table className="w-full min-w-[640px] text-left text-[13px]">
            <thead>
              <tr className="border-b border-zinc-100 text-[11px] uppercase tracking-wide text-zinc-400 dark:border-zinc-800">
                {[['rank', 'Rank', 'w-16'], ['name', 'General', ''], ['type', 'Type', ''], ['power', 'Power', ''], ['totAtk', 'Attack', ''], ['cov', 'Covenant', '']].map(([col, label, w]) => (
                  <th key={col} className={`px-4 py-2.5 font-medium ${w} ${['rank', 'power', 'name', 'totAtk'].includes(col) ? 'cursor-pointer select-none hover:text-zinc-600' : ''}`}
                    onClick={() => ['rank', 'power', 'name', 'totAtk'].includes(col) && setSortCol(col)}>
                    <span className="inline-flex items-center gap-1">{label}{sort === col && <Icon name="chevron" size={12} className={asc ? 'rotate-90' : '-rotate-90'} />}</span>
                  </th>
                ))}
                <th className="px-4 py-2.5 text-right font-medium">Owned</th>
              </tr>
            </thead>
            <tbody className="divide-y divide-zinc-50 dark:divide-zinc-800/60">
              {rows.map(g => {
                const owned = isOwned(g);
                return (
                  <tr key={g.name + g.type} onClick={() => setSel(g)}
                    className={`cursor-pointer transition-colors hover:bg-zinc-50 dark:hover:bg-zinc-800/40 ${owned ? '' : 'opacity-70'}`}>
                    <td className="px-4 py-2.5 tabular-nums text-zinc-400">#{g.rank}</td>
                    <td className="px-4 py-2.5"><div className="flex items-center gap-2.5"><Avatar name={g.name} size={28} /><span className="font-medium text-zinc-900 dark:text-white">{g.name}</span></div></td>
                    <td className="px-4 py-2.5"><TypeTag type={g.type} /></td>
                    <td className="px-4 py-2.5">
                      <div className="flex items-center gap-2"><span className="w-9 tabular-nums font-medium text-zinc-900 dark:text-white">{g.power}</span><div className="hidden w-16 sm:block"><Progress value={g.power} /></div></div>
                    </td>
                    <td className="px-4 py-2.5 tabular-nums text-zinc-600 dark:text-zinc-300">{g.totAtk}%</td>
                    <td className="px-4 py-2.5">
                      <div className="flex gap-1">
                        {g.cov.mc && <span className="rounded bg-brand/10 px-1.5 py-0.5 text-[10px] font-medium text-brand">MC</span>}
                        {[g.cov.c1, g.cov.c2, g.cov.c3].map((c, i) => c && <span key={i} className="rounded bg-blue-50 px-1.5 py-0.5 text-[10px] font-medium text-blue-600 dark:bg-blue-500/15 dark:text-blue-400">C{i + 1}</span>)}
                        {!(g.cov.mc || g.cov.c1 || g.cov.c2 || g.cov.c3) && <span className="text-zinc-300">—</span>}
                      </div>
                    </td>
                    <td className="px-4 py-2.5" onClick={e => e.stopPropagation()}><div className="flex justify-end"><Toggle on={owned} disabled={!canEdit} onClick={() => toggle(g)} /></div></td>
                  </tr>
                );
              })}
              {rows.length === 0 && <tr><td colSpan="7" className="py-12 text-center text-zinc-400">No generals match your filters.</td></tr>}
            </tbody>
          </table>
          )}
        </div>
      </Card>

      <GeneralDrawer g={sel} open={!!sel} onClose={() => setSel(null)} canEdit={canEdit} />
    </div>
  );
}
window.DatabasePage = DatabasePage;
