'use strict';

/**
 * Sistema modular de interação e espionagem dos Barões Falken.
 *
 * Este ficheiro concentra apenas:
 * - menu apresentado ao clicar num Barão Falken;
 * - criação e conservação dos relatórios de espionagem;
 * - geração determinística da formação defensiva;
 * - apresentação do relatório e dos respetivos detalhes.
 *
 * Não altera a resolução das batalhas, o mapa, os recursos ou os edifícios.
 */
(() => {
  const REPORT_TYPE = 'espionage';
  const DEFENSE_VERSION = 2;

  const ENEMY_UNITS = Object.freeze({
    spearman: { name: 'Lanceiro defensor', icon: '🔱' },
    swordsman: { name: 'Espadachim defensor', icon: '🗡️' },
    archer: { name: 'Arqueiro defensor', icon: '🏹' },
    knight: { name: 'Cavaleiro defensor', icon: '🐴' }
  });

  function stringHash(text) {
    let hash = 2166136261;
    for (const char of String(text || 'falken')) {
      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 distribute(total, random, weights) {
    const normalized = weights.map(weight => Math.max(0.01, Number(weight) || 0.01));
    const weightTotal = normalized.reduce((sum, value) => sum + value, 0);
    const result = normalized.map(weight => Math.floor(total * weight / weightTotal));
    let remaining = total - result.reduce((sum, value) => sum + value, 0);
    while (remaining > 0) {
      result[Math.floor(random() * result.length)] += 1;
      remaining -= 1;
    }
    return result;
  }

  function generateDefense(target) {
    const level = Math.max(1, Math.floor(Number(target?.level) || 1));
    const random = seededRandom(`${target?.id || 'npc'}:${level}:defense:${DEFENSE_VERSION}`);
    const totalUnits = Math.max(18, Math.round(28 + level * 5 + Math.pow(level, 1.24) * 2));
    const sectorTotals = distribute(totalUnits, random, [0.28 + random() * 0.12, 0.36 + random() * 0.16, 0.28 + random() * 0.12]);
    const sectorNames = ['Flanco esquerdo', 'Centro', 'Flanco direito'];
    const sectors = sectorTotals.map((sectorTotal, index) => {
      const unitWeights = index === 1
        ? [0.28 + random() * 0.15, 0.32 + random() * 0.13, 0.26 + random() * 0.14, level >= 4 ? 0.14 + random() * 0.08 : 0.01]
        : [0.35 + random() * 0.15, 0.22 + random() * 0.12, 0.34 + random() * 0.15, level >= 5 ? 0.09 + random() * 0.06 : 0.01];
      const counts = distribute(sectorTotal, random, unitWeights);
      return {
        id: index === 0 ? 'left' : index === 1 ? 'center' : 'right',
        name: sectorNames[index],
        wallBonus: Math.min(90, 8 + level * 3 + Math.floor(random() * 7)),
        gateBonus: index === 1 ? Math.min(90, 10 + level * 4 + Math.floor(random() * 8)) : 0,
        rangedBonus: Math.min(80, 5 + level * 2 + Math.floor(random() * 7)),
        units: {
          spearman: counts[0],
          swordsman: counts[1],
          archer: counts[2],
          knight: counts[3]
        }
      };
    });

    const toolBase = Math.max(0, Math.floor(level / 2));
    const defense = {
      version: DEFENSE_VERSION,
      targetId: target?.id,
      targetName: target?.name || 'Barão Falken',
      targetLevel: level,
      coordinates: { x: Number(target?.x) || 0, y: Number(target?.y) || 0 },
      accuracy: 100,
      counterEspionage: 0,
      totalUnits,
      wallLevel: Math.max(1, Math.ceil(level / 3)),
      gateLevel: Math.max(1, Math.ceil(level / 4)),
      moatLevel: level >= 8 ? Math.ceil((level - 5) / 4) : 0,
      tools: {
        stones: toolBase + Math.floor(random() * 3),
        fireArrows: Math.max(0, toolBase - 1 + Math.floor(random() * 3)),
        reinforcements: level >= 6 ? 1 + Math.floor(level / 5) : 0
      },
      loot: {
        wood: Number(target?.loot?.wood) || 0,
        stone: Number(target?.loot?.stone) || 0,
        food: Number(target?.loot?.food) || 0,
        coins: Number(target?.loot?.coins) || 0
      },
      sectors
    };
    return globalThis.ReinosFalkenDefenseTools?.enhanceDefense?.(defense, target) || defense;
  }

  function contextTarget(context, targetId) {
    return context?.getProfile?.()?.targets?.find(target => target.id === targetId) || null;
  }

  function contextReport(context, reportId) {
    return context?.getProfile?.()?.reports?.find(report => report.id === reportId) || null;
  }

  function resourceLine(data, format) {
    if (globalThis.ReinosResourceIcons?.line) {
      return globalThis.ReinosResourceIcons.line(data, format);
    }
    return `Madeira ${format(data.wood)} · Pedra ${format(data.stone)} · Comida ${format(data.food)} · Moedas ${format(data.coins)}`;
  }

  function openTargetActions(context, targetId) {
    const target = contextTarget(context, targetId);
    if (!target) return;
    const escape = context.escapeHtml;
    const cooling = Number(target.cooldownUntil) > context.now();
    const attackLabel = cooling ? `Protegido por ${context.formatTime(target.cooldownUntil - context.now())}` : 'Atacar';
    const progression = globalThis.ReinosFalkenProgression?.progress(target);
    const progressionText = progression?.maxed ? 'Nível máximo 80' : `${progression?.current || 0}/${progression?.needed || 1} vitórias para subir`;
    const profile = context.getProfile?.() || {};
    const ownPosition = profile.worldPosition || { x: 0, y: 0 };
    const targetPosition = { x: Number(target.x) || 0, y: Number(target.y) || 0 };
    const distance = globalThis.ReinosMarchTravelTime?.distanceBetween
      ? globalThis.ReinosMarchTravelTime.distanceBetween(ownPosition, targetPosition)
      : Math.hypot(targetPosition.x - (Number(ownPosition.x) || 0), targetPosition.y - (Number(ownPosition.y) || 0));
    const distanceText = Number.isFinite(distance) ? `${context.format(Math.round(distance * 10) / 10)} coordenadas` : '—';

    context.openModal(
      `${escape(target.name)} • Nível ${target.level}`,
      `<div class="falken-action-card">
        <img src="../assets/barao_falken.png" alt="Barão Falken" draggable="false" />
        <div class="falken-action-info">
          <strong>${escape(target.name)}</strong>
          <span>Coordenadas X ${target.x} • Y ${target.y}</span>
          <span>Distância do teu castelo: ${distanceText}</span>
          <span>Progresso: ${escape(progressionText)}</span>
          <span>Força conhecida: ${context.format(target.strength)}</span>
          <span>Saque máximo: ${resourceLine(target.loot, context.format)}</span>
        </div>
      </div>
      <p class="falken-action-help">Espia o castelo para descobrir a formação defensiva ou prepara imediatamente um ataque.</p>
      <div class="falken-action-options">
        <button class="falken-choice spy" data-action="falken-spy" data-id="${escape(target.id)}">
          <b>🔍 Espiar</b><small>Receber relatório militar</small>
        </button>
        <button class="falken-choice attack" data-action="attack-open" data-id="${escape(target.id)}" ${cooling ? 'disabled' : ''}>
          <b>⚔️ ${attackLabel}</b><small>${cooling ? 'Podes continuar a espiar' : 'Selecionar tropas e avançar'}</small>
        </button>
      </div>`,
      '<button class="secondary-btn" data-action="modal-close">Fechar</button>'
    );
  }

  async function spyTarget(context, targetId) {
    const target = contextTarget(context, targetId);
    if (!target) return;
    const profile = context.getProfile();
    const defense = generateDefense(target);
    const report = {
      id: context.uid('spy'),
      at: context.now(),
      title: `Espionagem: ${target.name} • Nv. ${target.level}`,
      result: 'spy',
      reportType: REPORT_TYPE,
      targetId: target.id,
      targetName: target.name,
      targetLevel: target.level,
      targetCoordinates: { x: target.x, y: target.y },
      text: `A espionagem revelou ${defense.totalUnits} defensores e a formação completa do castelo.`,
      spyData: defense
    };
    profile.reports.push(report);
    await context.persist(true);
    openEspionageReport(context, report.id);
    context.toast('Relatório de espionagem recebido.', 'success');
  }

  function playerTroopTotal(profile) {
    return Object.values(profile?.troops || {}).reduce((sum, value) => sum + (Number(value) || 0), 0);
  }

  function openEspionageReport(context, reportId) {
    const report = contextReport(context, reportId);
    if (!report?.spyData) return;
    const profile = context.getProfile();
    const user = context.getCurrentUser();
    const data = report.spyData;
    const escape = context.escapeHtml;
    const target = contextTarget(context, report.targetId);
    const attackDisabled = target && Number(target.cooldownUntil) > context.now();

    context.openModal(
      'Resultados de espionagem',
      `<div class="spy-report-sheet">
        <div class="spy-report-ribbon">Resultados de espionagem</div>
        <p class="spy-intro">A tua espionagem militar foi um sucesso. Um dos teus agentes observou as tropas deste local e preparou uma estimativa da sua força.</p>
        <div class="spy-target-title"><span>Espiar:</span><strong>${escape(report.targetName)} • Nv. ${report.targetLevel}</strong></div>
        <div class="spy-versus">
          <div class="spy-lord-card player"><div class="spy-avatar">♛</div><b>${escape(profile.kingdomName || user?.username || 'Jogador')}</b><span>Nível ${profile.level}</span><small>${playerTroopTotal(profile)} tropas disponíveis</small></div>
          <div class="spy-accuracy"><div>🔍 <b>${data.accuracy}%</b></div><div>🎭 <b>${data.counterEspionage}%</b></div><small>Precisão / risco</small></div>
          <div class="spy-lord-card enemy"><div class="spy-avatar">🏴</div><b>${escape(report.targetName)}</b><span>Nível ${report.targetLevel}</span><small>X ${data.coordinates.x} • Y ${data.coordinates.y}</small></div>
        </div>
        <div class="spy-summary-icons">
          <div><span>⚔️</span><b>${context.format(data.totalUnits)}</b><small>Defensores</small></div>
          <div><span>🪜</span><b>${context.format(data.tools.stones)}</b><small>Pedras</small></div>
          <div><span>🏹</span><b>${context.format(data.tools.fireArrows)}</b><small>Flechas</small></div>
        </div>
        <div class="spy-loot"><b>Saque observado</b><span>${resourceLine(data.loot, context.format)}</span></div>
      </div>`,
      `<button class="secondary-btn" data-action="modal-close">Fechar</button>
       <button class="secondary-btn spy-details-btn" data-action="espionage-details" data-report-id="${escape(report.id)}">📋 Detalhes</button>
       <button class="action-btn" data-action="attack-open" data-id="${escape(report.targetId)}" ${attackDisabled ? 'disabled' : ''}>⚔️ ${attackDisabled ? 'Castelo protegido' : 'Atacar agora'}</button>`
    );
    document.querySelector('.modal')?.classList.add('spy-modal');
  }

  function unitRows(units, context) {
    return Object.entries(units)
      .filter(([, count]) => Number(count) > 0)
      .map(([type, count]) => `<div class="defense-unit"><span>${ENEMY_UNITS[type]?.icon || '🛡️'} ${ENEMY_UNITS[type]?.name || type}</span><b>${context.format(count)}</b></div>`)
      .join('') || '<div class="defense-unit empty"><span>Sem unidades observadas</span><b>0</b></div>';
  }

  function openDefenseDetails(context, reportId) {
    const report = contextReport(context, reportId);
    if (!report?.spyData) return;
    const data = report.spyData;
    const escape = context.escapeHtml;
    const sectors = data.sectors.map(sector => `<article class="defense-sector ${sector.id}">
      <h4>${escape(sector.name)}</h4>
      <div class="defense-bonuses">
        <span>🧱 Muralha +${sector.wallBonus}%</span>
        ${sector.gateBonus ? `<span>🚪 Portão +${sector.gateBonus}%</span>` : ''}
        <span>🏹 Distância +${sector.rangedBonus}%</span>
      </div>
      ${globalThis.ReinosFalkenDefenseTools?.sectorSummaryHtml?.(sector, context) || ''}
      <div class="defense-units">${unitRows(sector.units, context)}</div>
    </article>`).join('');

    context.openModal(
      `Formação defensiva — ${escape(report.targetName)}`,
      `<div class="defense-report-head">
        <div><small>Relatório recolhido em</small><b>${new Date(report.at).toLocaleString('pt-PT')}</b></div>
        <div><small>Nível observado</small><b>${report.targetLevel}</b></div>
        <div><small>Total de defensores</small><b>${context.format(data.totalUnits)}</b></div>
      </div>
      <div class="defense-fortifications">
        <span>🧱 Muralha Nv. ${data.wallLevel}</span>
        <span>🚪 Portão Nv. ${data.gateLevel}</span>
        <span>🌊 Fosso Nv. ${data.moatLevel}</span>
        <span>🪖 Reforços ${context.format(data.tools.reinforcements)}</span>
      </div>
      <div class="defense-formation-grid">${sectors}</div>`,
      `<button class="secondary-btn" data-action="espionage-report-open" data-report-id="${escape(report.id)}">← Voltar ao relatório</button>
       <button class="action-btn" data-action="attack-open" data-id="${escape(report.targetId)}">⚔️ Preparar ataque</button>`
    );
    document.querySelector('.modal')?.classList.add('defense-modal');
  }

  function reportPresentation(report, context) {
    if (report?.reportType !== REPORT_TYPE || !report.spyData) return null;
    const escape = context.escapeHtml;
    return {
      label: 'Espionagem',
      className: 'report-spy',
      detailsHtml: `<div>${escape(report.text)}</div><button class="report-open-btn" data-action="espionage-report-open" data-report-id="${escape(report.id)}">Abrir relatório</button>`
    };
  }

  async function handleAction(action, actionElement, context) {
    if (action === 'falken-open') {
      openTargetActions(context, actionElement.dataset.id);
      return true;
    }
    if (action === 'falken-spy') {
      await spyTarget(context, actionElement.dataset.id);
      return true;
    }
    if (action === 'espionage-report-open') {
      openEspionageReport(context, actionElement.dataset.reportId);
      return true;
    }
    if (action === 'espionage-details') {
      openDefenseDetails(context, actionElement.dataset.reportId);
      return true;
    }
    return false;
  }

  globalThis.RealmFalkenEspionage = Object.freeze({
    REPORT_TYPE,
    generateDefense,
    openTargetActions,
    openEspionageReport,
    openDefenseDetails,
    reportPresentation,
    handleAction
  });
})();
