// ViG Command Center — Rally Team Buffs (monthly heatmap + import/export)
const { useState: useStateR, useMemo: useMemoR, useRef: useRefR, useEffect: useEffectR } = React;

const RL_TROOPS = ['Archer', 'Siege', 'Cav', 'Ground'];
const RL_STATS = ['Attack', 'Defense', 'Hp'];
const RL_TROOP_COLOR = { Archer: '#16a34a', Siege: '#9333ea', Cav: '#dc2626', Ground: '#2563eb' };
const RL_KEY = 'vig2_rally_data_v2';

function rallyHeat(t, dark) {
  if (t == null) return dark ? '#14161c' : '#f4f4f5';
  const a = 0.08 + Math.max(0, Math.min(1, t)) * 0.92;
  return dark ? `rgba(251,146,60,${a})` : `rgba(234,88,12,${a * 0.9})`;
}
function rallyText(t, dark) {
  if (t == null) return dark ? '#3f3f46' : '#a1a1aa';
  return t > 0.62 ? '#fff' : (dark ? '#e7e9ef' : '#7c2d12');
}

function RallyPage() {
  const dark = document.documentElement.classList.contains('dark');
  const [data, setData] = useStateR(() => LS.get(RL_KEY, null) || window.RALLY);
  const [monthIdx, setMonthIdx] = useStateR(() => LS.get('vig2_rally_month', 0));
  const [troop, setTroop] = useStateR('All');
  const [q, setQ] = useStateR('');
  const [hideEmpty, setHideEmpty] = useStateR(true);
  const [sortKey, setSortKey] = useStateR('total');
  const [io, setIo] = useStateR(false);
  const fileRef = useRefR(null);
  useEffectR(() => { LS.set(RL_KEY, data); }, [data]);
  useEffectR(() => { LS.set('vig2_rally_month', monthIdx); }, [monthIdx]);

  const month = data[Math.min(monthIdx, data.length - 1)];

  const cols = useMemoR(() => {
    return troop === 'All'
      ? RL_TROOPS.flatMap(tr => RL_STATS.map(st => ({ tr, st })))
      : RL_STATS.map(st => ({ tr: troop, st }));
  }, [troop]);

  // per-column min/max for heat normalization
  const colRange = useMemoR(() => {
    const r = {};
    cols.forEach(({ tr, st }) => {
      const vals = month.players.map(p => p.stats[tr][st]).filter(v => v != null);
      r[tr + '|' + st] = { min: Math.min(...vals), max: Math.max(...vals) };
    });
    return r;
  }, [month, cols]);

  const rows = useMemoR(() => {
    const ql = q.trim().toLowerCase();
    let list = month.players.map(p => {
      const focusCols = troop === 'All' ? RL_TROOPS.flatMap(tr => RL_STATS.map(st => p.stats[tr][st])) : RL_STATS.map(st => p.stats[troop][st]);
      const present = focusCols.filter(v => v != null);
      const total = present.reduce((s, v) => s + v, 0);
      return { ...p, total, dataCount: present.length };
    });
    if (hideEmpty) list = list.filter(p => p.dataCount > 0);
    if (ql) list = list.filter(p => p.name.toLowerCase().includes(ql));
    list.sort((a, b) => {
      if (sortKey === 'name') return a.name.localeCompare(b.name);
      if (sortKey === 'total') return b.total - a.total;
      const [tr, st] = sortKey.split('|');
      return (b.stats[tr][st] || 0) - (a.stats[tr][st] || 0);
    });
    return list;
  }, [month, troop, q, hideEmpty, sortKey]);

  const heatOf = (p, tr, st) => {
    const v = p.stats[tr][st]; if (v == null) return null;
    const rg = colRange[tr + '|' + st]; if (!rg || rg.max === rg.min) return 0.6;
    return (v - rg.min) / (rg.max - rg.min);
  };

  // KPIs
  const withData = month.players.filter(p => p.hasData).length;
  const topAtk = useMemoR(() => {
    let best = null;
    month.players.forEach(p => { const v = p.stats.Archer.Attack; if (v != null && (!best || v > best.v)) best = { name: p.name, v }; });
    return best;
  }, [month]);

  /* ---- import / export ---- */
  const exportCSV = () => {
    const header = ['Player', ...RL_TROOPS.flatMap(tr => RL_STATS.map(st => tr + '_' + st))];
    const lines = [header.join(',')];
    month.players.forEach(p => lines.push([p.name, ...RL_TROOPS.flatMap(tr => RL_STATS.map(st => p.stats[tr][st] ?? ''))].join(',')));
    const b = new Blob([lines.join('\n')], { type: 'text/csv' });
    const a = document.createElement('a'); a.href = URL.createObjectURL(b); a.download = `vig-rally-${month.month.replace(/\s/g, '-')}.csv`; a.click();
  };
  const exportJSON = () => {
    const b = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
    const a = document.createElement('a'); a.href = URL.createObjectURL(b); a.download = 'vig-rally-buffs.json'; a.click();
  };
  const importRaw = (raw) => {
    raw = raw.trim(); if (!raw) return;
    if (raw[0] === '[' || raw[0] === '{') { try { const j = JSON.parse(raw); if (Array.isArray(j)) { setData(j); setIo(false); return; } } catch (e) {} }
    const lines = raw.split(/\r?\n/).filter(Boolean);
    const head = lines[0].split(',').map(s => s.trim());
    const body = lines.slice(1);
    const players = body.map(l => {
      const c = l.split(',').map(s => s.trim());
      const stats = {}; RL_TROOPS.forEach(tr => { stats[tr] = {}; RL_STATS.forEach(st => { stats[tr][st] = null; }); });
      let has = false;
      head.forEach((h, i) => {
        if (i === 0) return;
        const [tr, st] = h.split('_');
        if (stats[tr] && RL_STATS.includes(st)) { const v = parseFloat(c[i]); if (!isNaN(v)) { stats[tr][st] = Math.round(v); has = true; } }
      });
      return { name: c[0], stats, hasData: has };
    }).filter(p => p.name);
    if (players.length) {
      const next = data.map((m, i) => i === monthIdx ? { ...m, players } : m);
      setData(next); setIo(false);
    }
  };

  const colW = troop === 'All' ? 56 : 96;

  return (
    <div className="space-y-4">
      {/* controls */}
      <div className="flex flex-wrap items-center gap-2.5">
        <Segmented options={data.map((m, i) => ({ value: i, label: m.month }))} value={monthIdx} onChange={setMonthIdx} />
        <div className="ml-auto flex items-center gap-2">
          <Btn variant="outline" size="sm" onClick={() => setIo(true)}><Icon name="download" size={14} />Import / Export</Btn>
        </div>
      </div>

      {/* active buffs banner */}
      <Card className="flex flex-wrap items-center gap-2 px-4 py-3">
        <span className="text-[11px] font-semibold uppercase tracking-wide text-zinc-400">Active buffs · {month.month}</span>
        <div className="flex flex-wrap gap-1.5">
          {month.activeBuffs.map(b => (
            <span key={b} className="inline-flex items-center gap-1 rounded-md bg-brand/10 px-2 py-0.5 text-[11.5px] font-medium text-brand"><Icon name="bolt" size={11} />{b}</span>
          ))}
        </div>
      </Card>

      {/* KPIs */}
      <div className="grid grid-cols-2 gap-3 lg:grid-cols-4">
        <Card className="p-3.5"><div className="text-[11px] uppercase tracking-wide text-zinc-400">Reporting</div><div className="mt-1 text-[24px] font-semibold tabular-nums text-zinc-900 dark:text-white">{withData}<span className="text-[14px] text-zinc-400">/{month.players.length}</span></div><div className="text-[11.5px] text-zinc-400">players with data</div></Card>
        <Card className="p-3.5"><div className="text-[11px] uppercase tracking-wide text-zinc-400">Top rally lead</div><div className="mt-1 text-[24px] font-semibold tabular-nums text-brand">{topAtk ? topAtk.v.toLocaleString() : '—'}</div><div className="text-[11.5px] text-zinc-400">{topAtk ? topAtk.name + ' · Archer ATK' : ''}</div></Card>
        <Card className="p-3.5"><div className="text-[11px] uppercase tracking-wide text-zinc-400">Showing</div><div className="mt-1 text-[24px] font-semibold tabular-nums text-zinc-900 dark:text-white">{rows.length}</div><div className="text-[11.5px] text-zinc-400">{troop === 'All' ? 'all troop types' : troop + ' focus'}</div></Card>
        <Card className="p-3.5"><div className="text-[11px] uppercase tracking-wide text-zinc-400">Snapshot set</div><div className="mt-1 text-[24px] font-semibold tabular-nums text-zinc-900 dark:text-white">{data.length}</div><div className="text-[11.5px] text-zinc-400">monthly reports</div></Card>
      </div>

      {/* filters */}
      <div className="flex flex-wrap items-center gap-2.5">
        <SearchInput value={q} onChange={setQ} placeholder="Search players…" className="w-full sm:w-56" />
        <Segmented options={['All', 'Archer', 'Siege', 'Cav', 'Ground']} value={troop} onChange={setTroop} />
        <button onClick={() => setHideEmpty(h => !h)} className={`inline-flex h-9 items-center gap-1.5 rounded-lg border px-3 text-[13px] font-medium transition-colors ${hideEmpty ? '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={hideEmpty ? 'check' : 'x'} size={14} />Hide empty
        </button>
      </div>

      {/* heatmap */}
      <Card className="overflow-hidden">
        <div className="overflow-x-auto">
          <table className="w-full border-collapse text-[12.5px]">
            <thead>
              {troop === 'All' && (
                <tr>
                  <th className="sticky left-0 z-10 bg-white dark:bg-zinc-900"></th>
                  {RL_TROOPS.map(tr => (
                    <th key={tr} colSpan="3" className="px-2 py-2 text-center">
                      <span className="inline-flex items-center gap-1.5 rounded-md px-2 py-0.5 text-[11px] font-semibold" style={{ background: RL_TROOP_COLOR[tr] + '18', color: RL_TROOP_COLOR[tr] }}>
                        <Icon name={{ Archer: 'target', Siege: 'bolt', Cav: 'flame', Ground: 'shield' }[tr]} size={12} />{tr}
                      </span>
                    </th>
                  ))}
                </tr>
              )}
              <tr className="border-b border-zinc-100 dark:border-zinc-800">
                <th onClick={() => setSortKey('name')} className="sticky left-0 z-10 cursor-pointer bg-white px-3 py-2 text-left text-[11px] font-semibold uppercase tracking-wide text-zinc-400 dark:bg-zinc-900">Player</th>
                {cols.map(({ tr, st }) => (
                  <th key={tr + st} onClick={() => setSortKey(tr + '|' + st)} className="cursor-pointer px-2 py-2 text-center text-[10.5px] font-semibold uppercase tracking-wide text-zinc-400 hover:text-zinc-600" style={{ minWidth: colW }}>
                    {troop !== 'All' && <span className="mr-1" style={{ color: RL_TROOP_COLOR[tr] }}>●</span>}{st === 'Hp' ? 'HP' : st.slice(0, 3)}
                    {sortKey === tr + '|' + st && <Icon name="chevron" size={10} className="ml-0.5 inline -rotate-90" />}
                  </th>
                ))}
                <th onClick={() => setSortKey('total')} className="cursor-pointer px-3 py-2 text-right text-[10.5px] font-semibold uppercase tracking-wide text-zinc-400">Total</th>
              </tr>
            </thead>
            <tbody>
              {rows.map((p, ri) => (
                <tr key={p.name + '_' + ri} className="group">
                  <td className="sticky left-0 z-10 bg-white px-3 py-1.5 dark:bg-zinc-900 group-hover:bg-zinc-50 dark:group-hover:bg-zinc-800/60">
                    <div className="flex items-center gap-2">
                      {sortKey === 'total' && ri < 3 && <span className="flex h-4 w-4 items-center justify-center rounded text-[9px] font-bold text-white" style={{ background: ['#FFB020', '#A8AEBF', '#C8865B'][ri] }}>{ri + 1}</span>}
                      <span className="font-medium text-zinc-900 dark:text-white">{p.name}</span>
                    </div>
                  </td>
                  {cols.map(({ tr, st }) => {
                    const t = heatOf(p, tr, st); const v = p.stats[tr][st];
                    return (
                      <td key={tr + st} className="p-0.5">
                        <div className="flex h-8 items-center justify-center rounded tabular-nums" style={{ background: rallyHeat(t, dark), color: rallyText(t, dark), minWidth: colW - 4, fontWeight: t != null && t > 0.62 ? 600 : 500 }}>
                          {v != null ? v.toLocaleString() : '·'}
                        </div>
                      </td>
                    );
                  })}
                  <td className="px-3 py-1.5 text-right font-semibold tabular-nums text-zinc-900 dark:text-white">{p.total ? p.total.toLocaleString() : '—'}</td>
                </tr>
              ))}
              {rows.length === 0 && <tr><td colSpan={cols.length + 2} className="py-12 text-center text-zinc-400">No players with data for this view.</td></tr>}
            </tbody>
          </table>
        </div>
      </Card>
      <p className="px-1 text-[11.5px] text-zinc-400">Cells are heat-shaded per column (deeper orange = higher within that stat). In-rally buff values measured against a dead keep. Click a column header to sort.</p>

      {/* import/export modal */}
      {io && (
        <div className="fixed inset-0 z-50 flex items-center justify-center p-4">
          <div onClick={() => setIo(false)} className="absolute inset-0 bg-zinc-900/40 backdrop-blur-sm"></div>
          <Card className="relative w-full max-w-lg p-5">
            <div className="flex items-center justify-between"><h3 className="text-sm font-semibold text-zinc-900 dark:text-white">Import / Export — {month.month}</h3><Btn variant="ghost" size="sm" onClick={() => setIo(false)}><Icon name="x" size={16} /></Btn></div>
            <div className="mt-3 flex flex-wrap gap-2">
              <Btn variant="outline" size="sm" onClick={exportCSV}><Icon name="download" size={14} />Export CSV (month)</Btn>
              <Btn variant="outline" size="sm" onClick={exportJSON}><Icon name="download" size={14} />Export JSON (all)</Btn>
              <Btn variant="ghost" size="sm" className="ml-auto !text-rose-500" onClick={() => { setData(window.RALLY); setIo(false); }}>Reset</Btn>
            </div>
            <ImportBox onImport={importRaw} fileRef={fileRef} />
          </Card>
        </div>
      )}
    </div>
  );
}

function ImportBox({ onImport, fileRef }) {
  const [text, setText] = useStateR('');
  return (
    <div className="mt-4">
      <div className="mb-1.5 text-[11.5px] text-zinc-500 dark:text-zinc-400">Paste CSV (<span className="font-mono">Player,Archer_Attack,…,Ground_Hp</span>) to replace the current month, or JSON to replace all months.</div>
      <textarea value={text} onChange={e => setText(e.target.value)} rows={6} placeholder="Player,Archer_Attack,Archer_Defense,Archer_Hp,…&#10;Zero,10467,6267,6925,…" className="w-full rounded-lg border border-zinc-200 bg-zinc-50 p-3 font-mono text-[12px] text-zinc-800 outline-none focus:border-brand dark:border-zinc-700 dark:bg-zinc-800/40 dark:text-zinc-100" style={{ resize: 'vertical' }}></textarea>
      <div className="mt-2 flex items-center gap-2">
        <input ref={fileRef} type="file" accept=".csv,.json,.txt" className="hidden" onChange={e => { const f = e.target.files[0]; if (f) { const rd = new FileReader(); rd.onload = () => onImport(String(rd.result)); rd.readAsText(f); } }} />
        <Btn variant="outline" size="sm" onClick={() => fileRef.current.click()}><Icon name="database" size={14} />Upload file</Btn>
        <Btn variant="brand" size="sm" className="ml-auto" onClick={() => onImport(text)}><Icon name="check" size={14} />Import</Btn>
      </div>
    </div>
  );
}
window.RallyPage = RallyPage;
