'use strict';

/**
 * Ferramentas defensivas dos Barões Falken.
 *
 * Responsabilidades exclusivas deste módulo:
 * - gerar ferramentas defensivas determinísticas por Barão, nível e setor;
 * - acrescentar os respetivos bónus à formação revelada pela espionagem;
 * - fornecer os dados necessários ao planeador inteligente e aos relatórios.
 *
 * Não altera tropas, progressão, saques ou resolução das batalhas.
 */
(() => {
  const VERSION = 1;

  const CATALOG = Object.freeze({
    wallStones: Object.freeze({
      id: 'wallStones',
      name: 'Pedras defensivas',
      shortName: 'Pedras',
      icon: '🪨',
      effectType: 'wall',
      bonusPerUnit: 10,
      description: 'Aumentam a proteção da muralha neste setor.'
    }),
    gateBraces: Object.freeze({
      id: 'gateBraces',
      name: 'Reforços de portão',
      shortName: 'Reforços',
      icon: '🛡️',
      effectType: 'gate',
      bonusPerUnit: 10,
      centerOnly: true,
      description: 'Aumentam a proteção do portão no ataque frontal.'
    }),
    fireArrows: Object.freeze({
      id: 'fireArrows',
      name: 'Flechas incendiárias',
      shortName: 'Flechas',
      icon: '🔥',
      effectType: 'ranged',
      bonusPerUnit: 5,
      description: 'Aumentam a força dos defensores à distância.'
    })
  });

  function stringHash(text) {
    let hash = 2166136261;
    for (const char of String(text || 'falken-defense-tools')) {
      hash ^= char.charCodeAt(0);
      hash = Math.imul(hash, 16777619);
    }
    return hash >>> 0;
  }

  function seededRandom(seedText) {
    let state = stringHash(seedText) || 1;
    return () => {
      state += 0x6D2B79F5;
      let value = state;
      value = Math.imul(value ^ (value >>> 15), value | 1);
      value ^= value + Math.imul(value ^ (value >>> 7), value | 61);
      return ((value ^ (value >>> 14)) >>> 0) / 4294967296;
    };
  }

  function safeCount(value) {
    return Math.max(0, Math.floor(Number(value) || 0));
  }

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

  function normalizeToolMap(value) {
    const result = emptyToolMap();
    Object.keys(result).forEach(type => { result[type] = safeCount(value?.[type]); });
    return result;
  }

  function countsForSector(target, sectorId) {
    const level = Math.max(1, Math.min(80, safeCount(target?.level) || 1));
    const random = seededRandom(`${target?.id || 'npc'}:${level}:${sectorId}:defensive-tools:${VERSION}`);

    // Todos os Barões têm proteção de muralha logo no nível 1. A quantidade
    // cresce por patamares para obrigar a preparar ferramentas de cerco.
    const wallStones = Math.min(8, 1 + Math.floor((level - 1) / 12) + (random() > 0.72 ? 1 : 0));
    const gateBraces = sectorId === 'center'
      ? Math.min(9, 1 + Math.floor((level - 1) / 10) + (random() > 0.75 ? 1 : 0))
      : 0;
    const fireArrows = level >= 2
      ? Math.min(7, 1 + Math.floor((level - 2) / 14) + (random() > 0.78 ? 1 : 0))
      : 0;

    return { wallStones, gateBraces, fireArrows };
  }

  function bonusesFromTools(tools) {
    const normalized = normalizeToolMap(tools);
    return Object.values(CATALOG).reduce((result, tool) => {
      result[tool.effectType] += normalized[tool.id] * tool.bonusPerUnit;
      return result;
    }, { wall: 0, gate: 0, ranged: 0 });
  }

  function enhanceSector(sector, target) {
    const defenseTools = countsForSector(target, sector?.id || 'center');
    const toolBonuses = bonusesFromTools(defenseTools);
    const baseBonuses = {
      wall: safeCount(sector?.wallBonus),
      gate: safeCount(sector?.gateBonus),
      ranged: safeCount(sector?.rangedBonus)
    };

    return {
      ...sector,
      baseBonuses,
      defenseTools,
      toolBonuses,
      wallBonus: baseBonuses.wall + toolBonuses.wall,
      gateBonus: baseBonuses.gate + toolBonuses.gate,
      rangedBonus: baseBonuses.ranged + toolBonuses.ranged
    };
  }

  function enhanceDefense(defense, target) {
    if (!defense || !Array.isArray(defense.sectors)) return defense;
    const sectors = defense.sectors.map(sector => enhanceSector(sector, target));
    const totals = sectors.reduce((result, sector) => {
      Object.keys(result).forEach(type => { result[type] += safeCount(sector.defenseTools?.[type]); });
      return result;
    }, emptyToolMap());

    return {
      ...defense,
      defensiveToolsVersion: VERSION,
      sectors,
      defensiveTools: totals,
      tools: {
        ...(defense.tools || {}),
        stones: totals.wallStones,
        fireArrows: totals.fireArrows,
        reinforcements: totals.gateBraces
      }
    };
  }

  function sectorSummaryHtml(sector, context) {
    if (!sector?.defenseTools || typeof sector.defenseTools !== 'object') return '';
    const tools = normalizeToolMap(sector.defenseTools);
    const format = context?.format || (value => String(value));
    const escape = context?.escapeHtml || (value => String(value));
    const chips = Object.entries(CATALOG)
      .filter(([type, tool]) => tools[type] > 0 && (!tool.centerOnly || sector?.id === 'center'))
      .map(([type, tool]) => `<span class="defense-tool-chip" title="${escape(tool.description)}"><b>${tool.icon} ${escape(tool.shortName)}</b><em>${format(tools[type])}</em><small>+${format(tools[type] * tool.bonusPerUnit)}%</small></span>`)
      .join('');
    return chips ? `<div class="defense-tool-list">${chips}</div>` : '<div class="defense-tool-list empty">Sem ferramentas defensivas</div>';
  }

  function attackToolNeeds(sector) {
    const siegeCatalog = globalThis.ReinosSiegeTools?.CATALOG || {};
    const wallPer = Math.max(1, Number(siegeCatalog.ladder?.effectPerUnit) || 10);
    const gatePer = Math.max(1, Number(siegeCatalog.ram?.effectPerUnit) || 10);
    const rangedPer = Math.max(1, Number(siegeCatalog.mantlet?.effectPerUnit) || 5);
    return {
      ladder: Math.ceil(Math.min(100, safeCount(sector?.wallBonus)) / wallPer),
      ram: sector?.id === 'center' ? Math.ceil(Math.min(100, safeCount(sector?.gateBonus)) / gatePer) : 0,
      mantlet: Math.ceil(Math.min(100, safeCount(sector?.rangedBonus)) / rangedPer)
    };
  }

  globalThis.ReinosFalkenDefenseTools = Object.freeze({
    VERSION,
    CATALOG,
    emptyToolMap,
    normalizeToolMap,
    bonusesFromTools,
    countsForSector,
    enhanceSector,
    enhanceDefense,
    sectorSummaryHtml,
    attackToolNeeds
  });
})();
