'use strict';

/**
 * Catálogo modular das ferramentas de cerco.
 *
 * Este ficheiro contém apenas os dados e os cálculos comuns usados pela
 * Oficina, pelo planeador de ataque e pela resolução das batalhas.
 */
(() => {
  const VERSION = 1;
  const QUEUE_LIMIT = 5;

  const CATALOG = Object.freeze({
    ladder: Object.freeze({
      id: 'ladder',
      name: 'Escada',
      shortName: 'Escada',
      description: 'Reduz a proteção da muralha dos defensores.',
      effectLabel: 'Proteção da muralha',
      effectType: 'wall',
      effectPerUnit: 10,
      maxReduction: 100,
      workshopLevel: 1,
      baseSeconds: 60,
      cost: Object.freeze({ wood: 28, coins: 12 })
    }),
    ram: Object.freeze({
      id: 'ram',
      name: 'Ariete',
      shortName: 'Ariete',
      description: 'Reduz a proteção do portão dos defensores.',
      effectLabel: 'Proteção do portão',
      effectType: 'gate',
      effectPerUnit: 10,
      maxReduction: 100,
      workshopLevel: 1,
      centerOnly: true,
      baseSeconds: 150,
      cost: Object.freeze({ wood: 45, stone: 12, coins: 24 })
    }),
    mantlet: Object.freeze({
      id: 'mantlet',
      name: 'Mantelete',
      shortName: 'Mantelete',
      description: 'Reduz a força das unidades defensoras à distância.',
      effectLabel: 'Força à distância',
      effectType: 'ranged',
      effectPerUnit: 5,
      maxReduction: 100,
      workshopLevel: 2,
      baseSeconds: 90,
      cost: Object.freeze({ wood: 35, stone: 10, coins: 15 })
    })
  });

  function icon(type, size = 'normal') {
    const cls = `siege-tool-icon siege-tool-icon-${type} siege-tool-icon-${size}`;
    if (type === 'ladder') {
      return `<span class="${cls}" role="img" aria-label="Escada"><svg viewBox="0 0 80 80" aria-hidden="true"><g fill="none" stroke-linecap="round" stroke-linejoin="round"><path d="M18 69 31 11M49 69 62 11" stroke="#78421f" stroke-width="8"/><path d="M21 58h31M24 46h31M27 34h31M30 22h31" stroke="#b8753b" stroke-width="6"/><path d="M18 69 31 11M49 69 62 11" stroke="#d49a61" stroke-width="2" opacity=".65"/></g></svg></span>`;
    }
    if (type === 'ram') {
      return `<span class="${cls}" role="img" aria-label="Ariete"><svg viewBox="0 0 90 80" aria-hidden="true"><path d="M13 53h54l10 8H22Z" fill="#75401f" stroke="#42210f" stroke-width="3"/><path d="M23 50 65 20l10 11-42 29Z" fill="#a65d2b" stroke="#4a2814" stroke-width="3"/><path d="m64 20 14-4 6 8-9 7Z" fill="#d8c7a1" stroke="#65583e" stroke-width="3"/><circle cx="28" cy="63" r="8" fill="#54321f" stroke="#25170f" stroke-width="3"/><circle cx="64" cy="63" r="8" fill="#54321f" stroke="#25170f" stroke-width="3"/></svg></span>`;
    }
    return `<span class="${cls}" role="img" aria-label="Mantelete"><svg viewBox="0 0 80 80" aria-hidden="true"><path d="M18 68V15l42 8v45Z" fill="#a06a3b" stroke="#4b2e18" stroke-width="4"/><path d="m22 19 34 8v16L22 35Z" fill="#b63635"/><path d="m22 39 34 8v17l-34-8Z" fill="#c99a56"/><path d="M32 17v50M48 21v47" stroke="#5d3a20" stroke-width="4"/><path d="m22 19 34 45M56 27 22 56" stroke="#e0ba78" stroke-width="3" opacity=".7"/></svg></span>`;
  }

  function ensureState(profile) {
    if (!profile || typeof profile !== 'object') return false;
    let changed = false;
    if (!profile.siegeTools || typeof profile.siegeTools !== 'object') {
      profile.siegeTools = {};
      changed = true;
    }
    for (const type of Object.keys(CATALOG)) {
      const value = Math.max(0, Math.floor(Number(profile.siegeTools[type]) || 0));
      if (profile.siegeTools[type] !== value) changed = true;
      profile.siegeTools[type] = value;
    }
    if (!Array.isArray(profile.workshopQueue)) {
      profile.workshopQueue = [];
      changed = true;
    }
    profile.workshopQueue = profile.workshopQueue
      .filter(item => item && CATALOG[item.type])
      .map(item => ({
        ...item,
        count: Math.max(1, Math.floor(Number(item.count) || 1)),
        startedAt: Number(item.startedAt) || Date.now(),
        endAt: Number(item.endAt) || Date.now()
      }));
    if (profile.siegeToolsVersion !== VERSION) {
      profile.siegeToolsVersion = VERSION;
      changed = true;
    }
    return changed;
  }

  function workshop(profile) {
    return profile?.buildings?.find(building => building.type === 'workshop') || null;
  }

  function workshopLevel(profile) {
    const building = workshop(profile);
    if (!building || building.status === 'constructing' || Number(building.level) < 1) return 0;
    return Math.max(1, Math.floor(Number(building.level) || 1));
  }

  function speedMultiplier(level) {
    return 1 + Math.max(0, Number(level) - 1) * 0.16;
  }

  function unitTimeMs(type, level) {
    const item = CATALOG[type];
    if (!item) return 0;
    return Math.max(1000, Math.round(item.baseSeconds * 1000 / speedMultiplier(level)));
  }

  function batchTimeMs(type, count, level) {
    return unitTimeMs(type, level) * Math.max(1, Math.floor(Number(count) || 1));
  }

  function batchCost(type, count) {
    const item = CATALOG[type];
    const amount = Math.max(1, Math.floor(Number(count) || 1));
    if (!item) return {};
    return Object.fromEntries(Object.entries(item.cost).map(([resource, value]) => [resource, value * amount]));
  }

  function emptyToolMap() {
    return Object.fromEntries(Object.keys(CATALOG).map(type => [type, 0]));
  }

  function normalizeToolMap(value) {
    const result = emptyToolMap();
    for (const type of Object.keys(result)) result[type] = Math.max(0, Math.floor(Number(value?.[type]) || 0));
    return result;
  }

  function effects(tools, flankId = 'center') {
    const normalized = normalizeToolMap(tools);
    const result = { wall: 0, gate: 0, ranged: 0 };
    for (const [type, count] of Object.entries(normalized)) {
      const item = CATALOG[type];
      if (!item || count < 1 || (item.centerOnly && flankId !== 'center')) continue;
      result[item.effectType] = Math.min(item.maxReduction, result[item.effectType] + count * item.effectPerUnit);
    }
    return result;
  }

  function applyToSector(sector, tools, flankId = 'center') {
    const reductions = effects(tools, flankId);
    return {
      reductions,
      wallBonus: Math.max(0, (Number(sector?.wallBonus) || 0) - reductions.wall),
      gateBonus: Math.max(0, (Number(sector?.gateBonus) || 0) - reductions.gate),
      rangedBonus: Math.max(0, (Number(sector?.rangedBonus) || 0) - reductions.ranged)
    };
  }

  globalThis.ReinosSiegeTools = Object.freeze({
    VERSION,
    QUEUE_LIMIT,
    CATALOG,
    icon,
    ensureState,
    workshop,
    workshopLevel,
    speedMultiplier,
    unitTimeMs,
    batchTimeMs,
    batchCost,
    emptyToolMap,
    normalizeToolMap,
    effects,
    applyToSector
  });
})();
