// ViG Command Center — Troop Training calculator
// Exact per-unit costs & power, T1–T16, as published in community data tables
// (matches 1366evony.com/troop_calculator). Lumber/Stone/Ore/Food/Gold + Power.
const { useState: useStateTT, useEffect: useEffectTT, useRef: useRefTT } = React;

const TT_TYPES = ['Ranged', 'Mounted', 'Ground', 'Siege'];
const TT_TYPE_IMG = { Ground: 'vig/assets/icons/infantry.png', Mounted: 'vig/assets/icons/cavalry.png', Ranged: 'vig/assets/icons/ranged.png', Siege: 'vig/assets/icons/siege.png' };
const TT_TYPE_BUILDING = { Ground: 'Barracks', Mounted: 'Stable', Ranged: 'Archer Camp', Siege: 'Workshop' };

/* per-tier arrays, index 0 = T1 … index 15 = T16 */
const TT_GOLD = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 800, 1300, 5000];
const TT_POWER = [2, 2.7, 3.65, 4.92, 6.64, 8.97, 12.11, 16.34, 22.06, 29.79, 35.75, 53.63, 81, 122, 163, 230, 400];
const TT_TABLE = {
  Mounted: {
    Lumber: [80, 130, 200, 220, 240, 260, 300, 420, 600, 850, 1300, 2000, 3000, 4500, 7500, 12200, 19500],
    Stone: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    Ore: [0, 0, 0, 120, 260, 580, 900, 1300, 1800, 2500, 3900, 6000, 9000, 13500, 22500, 36600, 58600],
    Food: [80, 130, 200, 220, 240, 260, 300, 420, 600, 850, 1300, 2000, 3000, 4500, 7500, 12200, 19500],
  },
  Ranged: {
    Lumber: [120, 160, 240, 320, 420, 660, 900, 1300, 1800, 2500, 3900, 6000, 9000, 13500, 22500, 36600, 58600],
    Stone: [0, 40, 80, 120, 160, 220, 300, 420, 600, 850, 1300, 2000, 3000, 4500, 7500, 12200, 19500],
    Ore: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    Food: [40, 60, 80, 120, 160, 220, 300, 420, 600, 850, 1300, 2000, 3000, 4500, 7500, 12200, 19500],
  },
  Ground: {
    Lumber: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    Stone: [0, 40, 80, 120, 160, 220, 300, 420, 600, 850, 1300, 2000, 3000, 4500, 7500, 12200, 19500],
    Ore: [0, 0, 0, 60, 120, 220, 300, 420, 600, 850, 1300, 2000, 3000, 4500, 7500, 12200, 19500],
    Food: [160, 220, 320, 380, 460, 660, 900, 1300, 1800, 2500, 3900, 6000, 9000, 13500, 22500, 36600, 58600],
  },
  Siege: {
    Lumber: [100, 120, 120, 120, 160, 220, 300, 420, 600, 850, 1300, 2000, 3000, 4500, 7500, 12200, 19500],
    Stone: [60, 140, 280, 320, 420, 660, 900, 1300, 1800, 2500, 3900, 6000, 9000, 13500, 22500, 36600, 58600],
    Ore: [0, 0, 0, 120, 160, 220, 300, 420, 600, 850, 1300, 2000, 3000, 4500, 7500, 12200, 19500],
    Food: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  },
};
const TT_RES_META = [
  ['Food', '#16a34a'],
  ['Lumber', '#a16207'],
  ['Stone', '#64748b'],
  ['Ore', '#dc2626'],
  ['Gold', '#ca8a04'],
];
function ttUnitCost(type, tierIdx, ds) {
  const TABLE = (ds && ds.TABLE) || TT_TABLE, GOLD = (ds && ds.GOLD) || TT_GOLD, POWER = (ds && ds.POWER) || TT_POWER;
  const t = TABLE[type];
  return { Food: t.Food[tierIdx], Lumber: t.Lumber[tierIdx], Stone: t.Stone[tierIdx], Ore: t.Ore[tierIdx], Gold: GOLD[tierIdx], Power: POWER[tierIdx] };
}

const ttFmt = n => Math.round(n).toLocaleString();
const ttBig = n => n >= 1e12 ? (n / 1e12).toFixed(2) + 'T' : n >= 1e9 ? (n / 1e9).toFixed(2) + 'B' : n >= 1e6 ? (n / 1e6).toFixed(2) + 'M' : n >= 1e3 ? (n / 1e3).toFixed(1) + 'K' : ttFmt(n);

const TT_CSS = `
@keyframes ttFloat { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
@keyframes ttPulse { 0%,100% { box-shadow: 0 0 0 0 rgba(255,107,0,.22); } 50% { box-shadow: 0 0 0 8px rgba(255,107,0,0); } }
.tt-icon { animation: ttFloat 3.2s ease-in-out infinite; }
.tt-power { animation: ttPulse 2.6s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .tt-icon, .tt-power { animation: none !important; } }
`;

/* animated count-up */
function useTTCount(v) {
  const [disp, setDisp] = useStateTT(v);
  const ref = useRefTT(v);
  useEffectTT(() => {
    const from = ref.current, to = v;
    if (from === to) return;
    const t0 = performance.now(), dur = 450;
    let raf;
    const step = now => {
      const k = Math.min(1, (now - t0) / dur), e = 1 - Math.pow(1 - k, 3);
      setDisp(from + (to - from) * e);
      if (k < 1) raf = requestAnimationFrame(step); else ref.current = to;
    };
    raf = requestAnimationFrame(step);
    // rAF doesn't fire in hidden/background tabs — guarantee the final value lands
    const tmr = setTimeout(() => { setDisp(to); ref.current = to; }, dur + 80);
    return () => { cancelAnimationFrame(raf); clearTimeout(tmr); ref.current = to; };
  }, [v]);
  return disp;
}
function TTResCard({ name, color, value, perUnit }) {
  const v = useTTCount(value);
  return (
    <Card className="p-4">
      <div className="flex items-center gap-2">
        <span className="h-2.5 w-2.5 rounded-full" style={{ background: color }}></span>
        <span className="text-[11px] font-bold uppercase tracking-wide" style={{ color }}>{name}</span>
      </div>
      <div className="mt-1.5 text-[24px] font-bold tabular-nums leading-none text-zinc-900 dark:text-white">{value ? ttBig(v) : '—'}</div>
      <div className="mt-1.5 text-[11px] tabular-nums text-zinc-400">{value ? ttFmt(v) : perUnit ? ttFmt(perUnit) + ' per troop' : 'not needed'}</div>
    </Card>
  );
}

function TroopTrainingCalc() {
  const [type, setType] = useStateTT(() => { const t = LS.get('vig2_tt_type', 'Ranged'); return TT_TYPES.includes(t) ? t : 'Ranged'; });
  const [tierIdx, setTierIdx] = useStateTT(() => {
    const t = LS.get('vig2_tt_tier', 15);
    if (typeof t === 'number' && t >= 0 && t <= 16) return t;
    const m = /^T(\d+)$/.exec(String(t)); // legacy 'T14' format
    return m ? Math.min(16, Math.max(0, parseInt(m[1]) - 1)) : 15;
  });
  const [amount, setAmount] = useStateTT(() => { const a = LS.get('vig2_tt_amount', 1000000); return typeof a === 'number' ? a : 1000000; });
  const [disc, setDisc] = useStateTT(() => LS.get('vig2_tt_disc', 0));
  const [io, setIo] = useStateTT(false);
  const ds = useOverride('troop_costs', { TABLE: TT_TABLE, GOLD: TT_GOLD, POWER: TT_POWER });
  useEffectTT(() => { LS.set('vig2_tt_type', type); }, [type]);
  useEffectTT(() => { LS.set('vig2_tt_tier', tierIdx); }, [tierIdx]);
  useEffectTT(() => { LS.set('vig2_tt_amount', amount); }, [amount]);
  useEffectTT(() => { LS.set('vig2_tt_disc', disc); }, [disc]);

  const unit = ttUnitCost(type, tierIdx, ds);
  const mult = (1 - Math.min(99, +disc || 0) / 100) * (amount || 0);
  const totals = { Food: unit.Food * mult, Lumber: unit.Lumber * mult, Stone: unit.Stone * mult, Ore: unit.Ore * mult, Gold: unit.Gold * mult };
  const power = unit.Power * (amount || 0);
  const powerDisp = useTTCount(power);

  return (
    <div className="space-y-4">
      <style>{TT_CSS}</style>

      {/* configuration */}
      <Card className="overflow-hidden">
        <div className="flex items-center gap-2.5 border-b border-zinc-100 px-4 py-3 dark:border-zinc-800">
          <img src={TT_TYPE_IMG[type]} alt="" className="tt-icon h-9 w-9 rounded-lg" />
          <div className="min-w-0 flex-1">
            <div className="text-[13px] font-bold uppercase tracking-wide text-zinc-900 dark:text-white">Configuration</div>
            <div className="truncate text-[11px] text-zinc-400">Exact in-game costs, T1–T17 — trained in the {TT_TYPE_BUILDING[type]}</div>
          </div>
          <DataIOButton onClick={() => setIo(true)} edited={DataIO.has('troop_costs')} />
        </div>
        <div className="space-y-4 p-4">
          {/* type */}
          <div>
            <label className="mb-1.5 block text-[11px] font-semibold uppercase tracking-wide text-zinc-400">Troop type</label>
            <div className="grid grid-cols-2 gap-2 sm:grid-cols-4">
              {TT_TYPES.map(t => (
                <button key={t} onClick={() => setType(t)} className={`flex items-center gap-2.5 rounded-xl border p-2.5 text-left transition-all ${type === t ? 'border-brand bg-brand/5 shadow-sm' : 'border-zinc-200 hover:border-zinc-300 dark:border-zinc-700 dark:hover:border-zinc-600'}`}>
                  <img src={TT_TYPE_IMG[t]} alt="" className={`h-9 w-9 rounded-lg ${type === t ? 'tt-icon' : ''}`} />
                  <div>
                    <div className={`text-[13px] font-bold ${type === t ? 'text-brand' : 'text-zinc-700 dark:text-zinc-200'}`}>{t}</div>
                    <div className="text-[10.5px] text-zinc-400">{TT_TYPE_BUILDING[t]}</div>
                  </div>
                </button>
              ))}
            </div>
          </div>
          {/* tier */}
          <div>
            <label className="mb-1.5 block text-[11px] font-semibold uppercase tracking-wide text-zinc-400">Troop tier</label>
            <div className="flex flex-wrap gap-1.5">
              {TT_POWER.map((_, i) => (
                <button key={i} onClick={() => setTierIdx(i)} className={`h-9 min-w-[44px] rounded-lg border px-2 text-[12.5px] font-bold tabular-nums transition-colors ${tierIdx === i ? 'border-brand bg-brand text-white shadow-sm' : 'border-zinc-200 text-zinc-500 hover:bg-zinc-50 dark:border-zinc-700 dark:text-zinc-400 dark:hover:bg-zinc-800'}`}>T{i + 1}</button>
              ))}
            </div>
          </div>
          {/* amount + buff */}
          <div className="flex flex-wrap items-end gap-x-6 gap-y-3">
            <div>
              <label className="mb-1.5 block text-[11px] font-semibold uppercase tracking-wide text-zinc-400">Amount to train</label>
              <div className="flex items-center gap-2">
                <input type="text" inputMode="numeric" value={amount ? amount.toLocaleString() : ''} placeholder="0"
                  onChange={e => setAmount(Math.max(0, parseInt(e.target.value.replace(/[^\d]/g, '')) || 0))}
                  className="h-11 w-40 rounded-lg border border-zinc-200 bg-white px-3 text-[16px] font-bold tabular-nums outline-none focus:border-brand dark:border-zinc-700 dark:bg-zinc-900" />
                <div className="flex gap-1">
                  {[100000, 500000, 1000000, 5000000].map(q => (
                    <button key={q} onClick={() => setAmount(q)} className={`rounded-md border px-2 py-1.5 text-[11px] font-semibold tabular-nums transition-colors ${amount === q ? 'border-brand bg-brand/10 text-brand' : 'border-zinc-200 text-zinc-400 hover:bg-zinc-50 dark:border-zinc-700 dark:hover:bg-zinc-800'}`}>{q >= 1000000 ? q / 1000000 + 'M' : q / 1000 + 'K'}</button>
                  ))}
                </div>
              </div>
            </div>
            <label className="flex items-center gap-2 pb-1 text-[12px] text-zinc-500">
              <Icon name="bolt" size={13} className="text-brand" />Training cost reduction
              <input type="number" min="0" max="99" value={disc || ''} placeholder="0" onChange={e => setDisc(Math.min(99, Math.max(0, +e.target.value || 0)))}
                className="h-9 w-16 rounded-lg border border-zinc-200 bg-white px-2 text-right text-[13px] tabular-nums outline-none focus:border-brand dark:border-zinc-700 dark:bg-zinc-900" /> %
            </label>
          </div>
          {/* base cost strip */}
          <div className="flex flex-wrap items-center gap-x-4 gap-y-1.5 rounded-xl bg-zinc-50 px-3.5 py-2.5 dark:bg-zinc-800/50">
            <span className="text-[11px] font-bold uppercase tracking-wide text-zinc-400">Base cost · 1 troop</span>
            {TT_RES_META.map(([r, color]) => unit[r] > 0 && (
              <span key={r} className="text-[12px] font-semibold tabular-nums" style={{ color }}>{r} {ttFmt(unit[r])}</span>
            ))}
            <span className="text-[12px] font-semibold tabular-nums text-brand">Power {unit.Power}</span>
          </div>
        </div>
      </Card>

      {/* total power */}
      <Card className="tt-power flex flex-wrap items-center gap-x-6 gap-y-2 border-brand/30 p-4">
        <div className="flex items-center gap-3">
          <img src={TT_TYPE_IMG[type]} alt="" className="tt-icon h-11 w-11 rounded-xl" />
          <div>
            <div className="text-[11px] font-semibold uppercase tracking-wide text-zinc-400">Total power gain</div>
            <div className="text-[28px] font-bold tabular-nums leading-tight text-brand">{power ? '+' + ttBig(powerDisp) : '—'}</div>
          </div>
        </div>
        {power > 0 && (
          <div className="text-[12px] text-zinc-500 dark:text-zinc-400">
            <b className="tabular-nums text-zinc-700 dark:text-zinc-200">{ttFmt(amount)}</b> × T{tierIdx + 1} {type}{disc > 0 && <> · costs include <b className="text-brand">−{disc}%</b> reduction</>}
          </div>
        )}
      </Card>

      {/* required resources */}
      <div>
        <div className="mb-2 flex items-center gap-1.5 text-[11px] font-bold uppercase tracking-wide text-zinc-400"><Icon name="layers" size={13} />Required resources</div>
        <div className="grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-5">
          {TT_RES_META.map(([r, color]) => <TTResCard key={r} name={r} color={color} value={totals[r]} perUnit={unit[r]} />)}
        </div>
      </div>

      <p className="px-1 text-[11.5px] text-zinc-400">Costs are the exact published in-game values per troop (T1–T17). Gold is only required from T14. The cost-reduction field applies your training-cost buffs (research, sub-cities) evenly to all resources.</p>

      {io && <DataIOModal title="Troop training costs" datasetKey="troop_costs" filename="vig-troop-costs.csv"
        isOverridden={DataIO.has('troop_costs')} onClose={() => setIo(false)}
        currentCSV={toCSV([['Type', 'Tier', 'Food', 'Lumber', 'Stone', 'Ore', 'Gold', 'Power'],
          ...TT_TYPES.flatMap(tp => ds.POWER.map((_, ti) => { const u = ttUnitCost(tp, ti, ds); return [tp, 'T' + (ti + 1), u.Food, u.Lumber, u.Stone, u.Ore, u.Gold, u.Power]; }))])}
        onImport={rows => {
          const TABLE = { Ground: {}, Mounted: {}, Ranged: {}, Siege: {} };
          TT_TYPES.forEach(tp => ['Food', 'Lumber', 'Stone', 'Ore'].forEach(r => TABLE[tp][r] = ds.TABLE[tp][r].slice()));
          const GOLD = ds.GOLD.slice(), POWER = ds.POWER.slice();
          let n = 0;
          rows.slice(1).forEach(r => {
            const tp = TT_TYPES.find(t => t.toLowerCase() === String(r[0]).trim().toLowerCase());
            const ti = parseInt(String(r[1]).replace(/[^\d]/g, '')) - 1;
            if (!tp || ti < 0 || ti > 16) return;
            const num = x => parseInt(String(x).replace(/[^\d.-]/g, '')) || 0;
            TABLE[tp].Food[ti] = num(r[2]); TABLE[tp].Lumber[ti] = num(r[3]); TABLE[tp].Stone[ti] = num(r[4]); TABLE[tp].Ore[ti] = num(r[5]);
            GOLD[ti] = num(r[6]); POWER[ti] = parseFloat(r[7]) || 0; n++;
          });
          if (!n) return { error: 'No valid rows (need Type + Tier columns).' };
          DataIO.set('troop_costs', { TABLE, GOLD, POWER });
          return { n };
        }} />}
    </div>
  );
}
window.TroopTrainingCalc = TroopTrainingCalc;
