// ViG Command Center v2 — Account Health engine + mission-control widgets
const { useState: useStateH, useEffect: useEffectH, useRef: useRefH, useMemo: useMemoH } = React;

/* ---------- scoring engine: reads every module's live state ---------- */
function vigOwnedNameSet() {
  const own = LS.get('vig2_ownership', null) || {};
  const s = new Set();
  if (Object.keys(own).length) {
    Object.entries(own).forEach(([k, v]) => { if (v) s.add(k.split('|')[0].toLowerCase()); });
  } else { window.VIG.generals.forEach(g => { if (g.owned) s.add(g.name.toLowerCase()); }); }
  return s;
}
const clamp100 = v => Math.max(0, Math.min(100, v));

function computeHealth() {
  const owned = vigOwnedNameSet();
  // Generals (25%): power-weighted ownership
  const gens = window.VIG.generals;
  const totPow = gens.reduce((s, g) => s + g.power, 0);
  const ownPow = gens.reduce((s, g) => s + (owned.has(g.name.toLowerCase()) ? g.power : 0), 0);
  const generals = clamp100(ownPow / totPow * 100);
  // Buffs (20%): covenant completion avg
  const covs = window.VIG.covenants;
  let covPct = 0; covs.forEach(c => { const m = [c.main, c.c1, c.c2, c.c3].filter(Boolean); covPct += m.filter(n => owned.has(n.toLowerCase())).length / m.length; });
  const buffs = clamp100(covPct / covs.length * 100);
  // Equipment (15%): gear builds + dragon assignments
  const bA = LS.get('vig2_gear_v1_a', {}) || {}, bB = LS.get('vig2_gear_v1_b', {}) || {};
  const slotsFilled = Object.values(bA).filter(Boolean).length + Object.values(bB).filter(Boolean).length;
  const drag = Object.keys(LS.get('vig2_dragon_assign', {}) || {}).length;
  const equipment = clamp100((slotsFilled / 12 * 70) + (drag / 4 * 30));
  // Troops (10%): war hall + march config + presets
  const wh = LS.get('vig2_rc_wh', 0) || 0;
  const march = LS.get('vig2_march_size_v2', 0) || 0;
  const troops = clamp100((wh / 50 * 60) + (march > 0 ? 40 : 0));
  // Research (20%): specialty + champion + senate progression
  const fx = LS.get('vig2_fx_cur', 0) || 0, ch = LS.get('vig2_ch_cur', 0) || 0, sen = LS.get('vig2_sen_tier', 1) || 1;
  const research = clamp100((fx / 100 * 100 + ch / 28 * 100 + sen / 7 * 100) / 3);
  // Keep development (10%): construction progress + ideal land targets
  const cnDone = Object.values(LS.get('vig2_cn_done', {}) || {}).filter(Boolean).length;
  const land = LS.get('vig2_land_v1', {}) || {};
  const landLv = Object.values(land).reduce((s, b) => s + (b.target || 0), 0);
  const keep = clamp100((cnDone / 10 * 60) + (landLv / 480 * 40));

  const modules = [
    { id: 'generals', label: 'Generals', score: Math.round(generals), weight: 25, page: 'generals', action: 'Mark owned generals & chase top-ranked missing ones in the General Database' },
    { id: 'research', label: 'Research', score: Math.round(research), weight: 20, page: 'flexspec', action: 'Push Flexible Specialty, Champion Hall and Senate progression levels' },
    { id: 'buffs', label: 'Buffs', score: Math.round(buffs), weight: 20, page: 'optimizer', action: 'Complete the highest-value covenants flagged by the Optimizer' },
    { id: 'equipment', label: 'Equipment', score: Math.round(equipment), weight: 15, page: 'gear', action: 'Build full 6-piece loadouts in the Gear Calculator & assign all 4 dragons' },
    { id: 'troops', label: 'Troops', score: Math.round(troops), weight: 10, page: 'rallysize', action: 'Configure your march size & rally capacity in Troop Operations' },
    { id: 'keep', label: 'Keep Dev', score: Math.round(keep), weight: 10, page: 'construction', action: 'Track K-level construction progress & set Ideal Land targets' },
  ];
  const score = Math.round(modules.reduce((s, m) => s + m.score * m.weight, 0) / 100);

  // readiness scores
  const readiness = [
    { label: 'PvP', value: Math.round(generals * 0.4 + equipment * 0.3 + buffs * 0.3) },
    { label: 'Battlefield', value: Math.round(troops * 0.5 + generals * 0.3 + buffs * 0.2) },
    { label: 'Event', value: Math.round((research + keep) / 2) },
  ];

  // alliance position (live store if synced, else bundled)
  const alData = LS.get('vig2_alliance_data_v1', null) || window.ALLIANCE;
  const ranked = [...alData.alliances].sort((a, b) => b.power - a.power);
  const vigRank = ranked.findIndex(a => a.id === 'VIG') + 1;
  const vig = ranked.find(a => a.id === 'VIG');
  const leader = ranked[0];

  // recommendations: weakest-first
  const recs = [...modules].sort((a, b) => a.score - b.score).filter(m => m.score < 85)
    .map((m, i) => ({ ...m, priority: i + 1, severity: m.score < 40 ? 'critical' : m.score < 65 ? 'warning' : 'ok' }));
  const alerts = recs.filter(r => r.severity === 'critical');

  // trend
  const hist = LS.get('vig2_health_hist', []);
  let trend = 0;
  if (hist.length === 0 || Math.abs(hist[hist.length - 1].s - score) >= 1) {
    const next = [...hist, { s: score, t: Date.now() }].slice(-30);
    LS.set('vig2_health_hist', next);
    trend = hist.length ? score - hist[hist.length - 1].s : 0;
  } else if (hist.length > 1) trend = hist[hist.length - 1].s - hist[hist.length - 2].s;

  return { modules, score, readiness, recs, alerts, alliance: { rank: vigRank, power: vig ? vig.power : 0, leader: leader ? leader.id : '', gap: vig && leader ? Math.round((leader.power - vig.power) * 10) / 10 : 0, total: ranked.length }, trend, hist: LS.get('vig2_health_hist', []) };
}

/* ---------- animation: count-up ---------- */
function useCountUp(target, dur = 900) {
  const [val, setVal] = useStateH(0);
  const ref = useRefH(null);
  useEffectH(() => {
    const from = ref.current == null ? 0 : ref.current;
    const start = performance.now();
    let raf;
    const tick = (now) => {
      const p = Math.min(1, (now - start) / dur);
      const eased = 1 - Math.pow(1 - p, 3);
      setVal(from + (target - from) * eased);
      if (p < 1) raf = requestAnimationFrame(tick); else ref.current = target;
    };
    raf = requestAnimationFrame(tick);
    const failsafe = setTimeout(() => { setVal(target); ref.current = target; }, dur + 150);
    return () => { cancelAnimationFrame(raf); clearTimeout(failsafe); };
  }, [target]);
  return val;
}

function scoreColor(v) { return v >= 80 ? '#00C853' : v >= 60 ? '#FFC107' : v >= 40 ? '#FF7043' : '#FF1744'; }

/* ---------- big health ring ---------- */
function HealthRing({ score, size = 168 }) {
  const v = useCountUp(score);
  const r = (size - 18) / 2, c = 2 * Math.PI * r;
  const col = scoreColor(score);
  return (
    <div className="relative" style={{ width: size, height: size }}>
      <svg width={size} height={size} className="-rotate-90">
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" strokeWidth="11" stroke="#1f1f1f" />
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" strokeWidth="11" stroke={col} strokeLinecap="round"
          strokeDasharray={`${v / 100 * c} ${c}`} style={{ transition: 'stroke 0.4s', filter: `drop-shadow(0 0 10px ${col}44)` }} />
      </svg>
      <div className="absolute inset-0 flex flex-col items-center justify-center">
        <span className="text-[42px] font-extrabold leading-none tabular-nums text-white">{Math.round(v)}</span>
        <span className="mt-1 text-[10px] font-semibold uppercase tracking-[0.18em] text-zinc-500">Health</span>
      </div>
    </div>
  );
}

/* ---------- readiness gauge (semicircle) ---------- */
function Gauge({ value, label, size = 120 }) {
  const v = useCountUp(value);
  const r = (size - 16) / 2, c = Math.PI * r;
  const col = scoreColor(value);
  return (
    <div className="flex flex-col items-center">
      <div className="relative" style={{ width: size, height: size / 2 + 14 }}>
        <svg width={size} height={size / 2 + 8} viewBox={`0 0 ${size} ${size / 2 + 8}`}>
          <path d={`M 8 ${size / 2 + 4} A ${r} ${r} 0 0 1 ${size - 8} ${size / 2 + 4}`} fill="none" strokeWidth="9" stroke="#1f1f1f" strokeLinecap="round" />
          <path d={`M 8 ${size / 2 + 4} A ${r} ${r} 0 0 1 ${size - 8} ${size / 2 + 4}`} fill="none" strokeWidth="9" stroke={col} strokeLinecap="round"
            strokeDasharray={`${v / 100 * c} ${c}`} style={{ transition: 'stroke 0.4s' }} />
        </svg>
        <div className="absolute inset-x-0 bottom-0 text-center text-[20px] font-bold tabular-nums text-white">{Math.round(v)}</div>
      </div>
      <span className="mt-1 text-[10px] font-semibold uppercase tracking-[0.15em] text-zinc-500">{label}</span>
    </div>
  );
}

/* ---------- radar chart (6 axes) ---------- */
function Radar({ modules, size = 250 }) {
  const cx = size / 2, cy = size / 2, R = size / 2 - 34;
  const n = modules.length;
  const pt = (i, frac) => { const a = -Math.PI / 2 + i * 2 * Math.PI / n; return [cx + Math.cos(a) * R * frac, cy + Math.sin(a) * R * frac]; };
  const poly = modules.map((m, i) => pt(i, Math.max(0.04, m.score / 100)).join(',')).join(' ');
  return (
    <svg width="100%" viewBox={`0 0 ${size} ${size}`} style={{ display: 'block', maxWidth: size, margin: '0 auto' }}>
      {[0.25, 0.5, 0.75, 1].map(f => <polygon key={f} points={modules.map((_, i) => pt(i, f).join(',')).join(' ')} fill="none" stroke="#222" strokeWidth="1" />)}
      {modules.map((_, i) => { const [x, y] = pt(i, 1); return <line key={i} x1={cx} y1={cy} x2={x} y2={y} stroke="#222" strokeWidth="1" />; })}
      <polygon points={poly} fill="var(--brand-fill)" stroke="var(--brand-hex)" strokeWidth="2" strokeLinejoin="round" style={{ transition: 'all 0.6s ease', filter: 'drop-shadow(0 0 8px var(--brand-glow))' }} />
      {modules.map((m, i) => { const [x, y] = pt(i, Math.max(0.04, m.score / 100)); return <circle key={i} cx={x} cy={y} r="3.2" fill="var(--brand-hex)" />; })}
      {modules.map((m, i) => { const [x, y] = pt(i, 1.2); return <text key={i} x={x} y={y} textAnchor="middle" dominantBaseline="middle" fontSize="9.5" fontWeight="600" fill="#A0A0A0" style={{ textTransform: 'uppercase', letterSpacing: '0.08em' }}>{m.label}</text>; })}
    </svg>
  );
}

Object.assign(window, { computeHealth, useCountUp, scoreColor, HealthRing, Gauge, Radar });
