'use strict';

/**
 * Relatórios de defesa recebidos pelo jogador atacado.
 *
 * Este módulo é independente dos relatórios do atacante. Guarda o relatório
 * diretamente no perfil do defensor para que fique disponível mesmo que o
 * jogador estivesse offline quando a batalha foi resolvida.
 */
(() => {
  const REPORT_TYPE = 'battle-defense';
  const REPORT_VERSION = 2;
  const FLANKS = Object.freeze([
    { id: 'left', name: 'Flanco esquerdo', icon: '◀' },
    { id: 'center', name: 'Frontal', icon: '◆' },
    { id: 'right', name: 'Flanco direito', icon: '▶' }
  ]);

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

  function cloneTroops(troops, troopMeta = {}) {
    const types = new Set([...Object.keys(troopMeta || {}), ...Object.keys(troops || {})]);
    return Object.fromEntries([...types].map(type => [type, safeNumber(troops?.[type])]));
  }

  function totalTroops(troops) {
    return Object.values(troops || {}).reduce((sum, count) => sum + safeNumber(count), 0);
  }

  function troopDifference(initial, survivors, troopMeta = {}) {
    const result = cloneTroops(initial, troopMeta);
    Object.keys(result).forEach(type => {
      result[type] = Math.max(0, safeNumber(initial?.[type]) - safeNumber(survivors?.[type]));
    });
    return result;
  }

  function normalizeLoot(loot) {
    return {
      wood: safeNumber(loot?.wood),
      stone: safeNumber(loot?.stone),
      food: safeNumber(loot?.food),
      coins: safeNumber(loot?.coins)
    };
  }

  function normalizeSector(source, troopMeta = {}) {
    return {
      id: String(source?.id || ''),
      name: String(source?.name || ''),
      wallBonus: safeNumber(source?.wallBonus),
      gateBonus: safeNumber(source?.gateBonus),
      rangedBonus: safeNumber(source?.rangedBonus),
      units: cloneTroops(source?.units, troopMeta)
    };
  }

  function normalizePayload(payload, context) {
    const troopMeta = context.getTroopsMeta?.() || {};
    const attackBySector = {};
    const defenseInitial = {};
    const defenseFinal = {};

    FLANKS.forEach(flank => {
      const attack = payload.attackBySector?.[flank.id] || {};
      attackBySector[flank.id] = {
        sent: cloneTroops(attack.sent, troopMeta),
        wallSurvivors: cloneTroops(attack.wallSurvivors, troopMeta),
        toolsUsed: globalThis.ReinosSiegeTools?.normalizeToolMap?.(attack.toolsUsed) || {},
        toolReductions: {
          wall: safeNumber(attack.toolReductions?.wall),
          gate: safeNumber(attack.toolReductions?.gate),
          ranged: safeNumber(attack.toolReductions?.ranged)
        }
      };
      defenseInitial[flank.id] = normalizeSector(payload.defenseInitial?.[flank.id] || { id: flank.id, name: flank.name }, troopMeta);
      defenseFinal[flank.id] = normalizeSector(payload.defenseFinal?.[flank.id] || { id: flank.id, name: flank.name }, troopMeta);
    });

    const troopsSent = cloneTroops(payload.troopsSent, troopMeta);
    const troopsSurvived = cloneTroops(payload.troopsSurvived, troopMeta);

    return {
      version: REPORT_VERSION,
      attackerWon: Boolean(payload.victory),
      defenderWon: !Boolean(payload.victory),
      attackerName: String(payload.attackerName || 'Atacante desconhecido'),
      attackerKingdom: String(payload.attackerKingdom || ''),
      attackerLevel: Math.max(1, safeNumber(payload.attackerLevel) || 1),
      defenderName: String(payload.defenderName || 'Castelo defensor'),
      defenderLevel: Math.max(1, safeNumber(payload.defenderLevel) || 1),
      coordinates: {
        x: Math.round(Number(payload.coordinates?.x) || 0),
        y: Math.round(Number(payload.coordinates?.y) || 0)
      },
      originCoordinates: {
        x: Math.round(Number(payload.originCoordinates?.x) || 0),
        y: Math.round(Number(payload.originCoordinates?.y) || 0)
      },
      wavesUsed: safeNumber(payload.wavesUsed),
      usedFlanks: [...new Set((payload.usedFlanks || []).filter(id => FLANKS.some(flank => flank.id === id)))],
      breachedFlanks: [...new Set((payload.breachedFlanks || []).filter(id => FLANKS.some(flank => flank.id === id)))],
      courtyardBonus: Number(payload.courtyardBonus) || 0,
      loot: normalizeLoot(payload.loot),
      troopsSent,
      troopsSurvived,
      troopsLost: troopDifference(troopsSent, troopsSurvived, troopMeta),
      toolsUsed: globalThis.ReinosSiegeTools?.normalizeToolMap?.(payload.toolsUsed) || {},
      attackBySector,
      defenseInitial,
      defenseFinal,
      courtyard: {
        attackersEntered: cloneTroops(payload.courtyard?.attackersEntered, troopMeta),
        attackersSurvived: cloneTroops(payload.courtyard?.attackersSurvived, troopMeta),
        defendersBefore: safeNumber(payload.courtyard?.defendersBefore),
        defendersAfter: safeNumber(payload.courtyard?.defendersAfter),
        attackPower: safeNumber(payload.courtyard?.attackPower),
        defensePower: safeNumber(payload.courtyard?.defensePower)
      }
    };
  }

  function create(context, defenderProfile, payload) {
    if (!defenderProfile) return null;
    defenderProfile.reports = Array.isArray(defenderProfile.reports) ? defenderProfile.reports : [];
    const data = normalizePayload(payload, context);
    const ownInitial = FLANKS.reduce((sum, flank) => sum + totalTroops(data.defenseInitial[flank.id]?.units), 0);
    const ownFinal = FLANKS.reduce((sum, flank) => sum + totalTroops(data.defenseFinal[flank.id]?.units), 0);
    const ownLosses = Math.max(0, ownInitial - ownFinal);
    const stolen = Object.values(data.loot).reduce((sum, value) => sum + safeNumber(value), 0);

    const report = {
      id: context.uid('defense-battle'),
      at: context.now(),
      title: data.defenderWon
        ? `Defesa vitoriosa contra ${data.attackerName}`
        : `Castelo saqueado por ${data.attackerName}`,
      result: data.defenderWon ? 'win' : 'loss',
      reportType: REPORT_TYPE,
      text: data.defenderWon
        ? `As tuas defesas repeliram o ataque de ${data.attackerName}. Perdeste ${context.format(ownLosses)} defensor(es).`
        : `${data.attackerName} venceu a defesa e levou recursos do teu castelo${stolen > 0 ? '.' : ', mas não conseguiu transportar saque.'}`,
      defenseBattleData: data
    };
    defenderProfile.reports.push(report);
    return report;
  }

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

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

  function totalTools(tools) {
    return Object.values(tools || {}).reduce((sum, count) => sum + safeNumber(count), 0);
  }

  function toolChips(tools, context) {
    const catalog = globalThis.ReinosSiegeTools?.CATALOG || {};
    const rows = Object.entries(catalog)
      .filter(([type]) => safeNumber(tools?.[type]) > 0)
      .map(([type, tool]) => `<span class="battle-tool-chip">${globalThis.ReinosSiegeTools.icon(type, 'normal')}<b>${context.format(tools[type])}</b><small>${context.escapeHtml(tool.name)}</small></span>`);
    return rows.length ? rows.join('') : '<span class="battle-tool-none">Sem ferramentas</span>';
  }

  function resourceCards(resources, context) {
    return ['wood', 'stone', 'food', 'coins'].map(type => {
      const icon = globalThis.ReinosResourceIcons?.icon?.(type) || '◆';
      return `<div class="battle-loot-card">${icon}<b>${context.format(resources?.[type] || 0)}</b></div>`;
    }).join('');
  }

  function troopChips(troops, context) {
    const troopMeta = context.getTroopsMeta?.() || {};
    const rows = Object.entries(troopMeta)
      .map(([type, meta]) => ({ meta, count: safeNumber(troops?.[type]) }))
      .filter(item => item.count > 0);
    if (!rows.length) return '<span class="battle-troop-chip empty">0</span>';
    return rows.map(({ meta, count }) => `<span class="battle-troop-chip" title="${context.escapeHtml(meta.name)}">${meta.icon || '⚔️'} <b>${context.format(count)}</b></span>`).join('');
  }

  function troopRows(troops, context) {
    const troopMeta = context.getTroopsMeta?.() || {};
    const rows = Object.entries(troopMeta).map(([type, meta]) => ({ meta, count: safeNumber(troops?.[type]) }));
    return rows.map(({ meta, count }) => `<div class="battle-troop-row"><span>${meta.icon || '⚔️'} ${context.escapeHtml(meta.name || '')}</span><b>${context.format(count)}</b></div>`).join('');
  }

  function defenseTotals(data) {
    const initial = FLANKS.reduce((sum, flank) => sum + totalTroops(data.defenseInitial?.[flank.id]?.units), 0);
    const final = FLANKS.reduce((sum, flank) => sum + totalTroops(data.defenseFinal?.[flank.id]?.units), 0);
    return { initial, final, lost: Math.max(0, initial - final) };
  }

  function openSummary(context, reportId) {
    const report = findReport(context, reportId);
    if (!report?.defenseBattleData) return;
    const data = report.defenseBattleData;
    const defense = defenseTotals(data);
    const attackerSent = totalTroops(data.troopsSent);
    const attackerSurvived = totalTroops(data.troopsSurvived);
    const attackerLost = totalTroops(data.troopsLost);
    const title = data.defenderWon ? 'Defesa vitoriosa!' : 'O castelo foi saqueado';

    context.openModal(
      title,
      `<div class="battle-report-sheet defense-perspective ${data.defenderWon ? 'victory' : 'defeat'}">
        <header class="battle-report-ribbon">
          <h2>${title}</h2>
          <span>Ataque de ${context.escapeHtml(data.attackerName)}</span>
        </header>
        <div class="battle-report-meta">
          <div><b>Teu castelo: X ${data.coordinates.x} • Y ${data.coordinates.y}</b><small>${new Date(report.at).toLocaleString('pt-PT')}</small></div>
          <div class="battle-report-result-seal">${data.defenderWon ? '🛡️' : '🔥'}</div>
        </div>
        <div class="battle-report-scene" aria-hidden="true">
          <div class="battle-scene-army">⚔️ 🏹 🛡️</div>
          <div class="battle-scene-fortress">🏰</div>
        </div>
        <div class="battle-summary-grid">
          <section class="battle-lord-card attacker">
            <small>Atacante</small><h3>${context.escapeHtml(data.attackerName)}</h3>
            <span>${context.escapeHtml(data.attackerKingdom || 'Castelo atacante')} • Nv. ${context.format(data.attackerLevel)}</span>
            <div class="battle-big-stat"><b>${context.format(attackerSent)}</b><small>tropas enviadas</small></div>
            <div class="battle-mini-stats"><span>Sobreviventes <b>${context.format(attackerSurvived)}</b></span><span>Baixas <b>${context.format(attackerLost)}</b></span></div>
          </section>
          <section class="battle-result-card defense-result-card">
            <div><span>Resultado</span><b>${data.defenderWon ? 'Defesa venceu' : 'Defesa derrotada'}</b></div>
            <div><span>Vagas inimigas</span><b>${context.format(data.wavesUsed)}</b></div>
            <div><span>Flancos atacados</span><b>${context.format(data.usedFlanks.length)}</b></div>
            <div><span>Brechas sofridas</span><b>${context.format(data.breachedFlanks.length)}</b></div>
            <div><span>Ferramentas inimigas</span><b>${context.format(totalTools(data.toolsUsed))}</b></div>
          </section>
          <section class="battle-lord-card defender">
            <small>Defensor</small><h3>${context.escapeHtml(data.defenderName)}</h3>
            <span>Nível ${context.format(data.defenderLevel)}</span>
            <div class="battle-big-stat"><b>${context.format(defense.initial)}</b><small>defensores presentes</small></div>
            <div class="battle-mini-stats"><span>Restantes <b>${context.format(defense.final)}</b></span><span>Baixas <b>${context.format(defense.lost)}</b></span></div>
          </section>
        </div>
        <section class="battle-loot-section">
          <h4>${data.attackerWon ? 'Recursos roubados' : 'Recursos protegidos'}</h4>
          <div class="battle-loot-grid">${resourceCards(data.loot, context)}</div>
          <small>${data.attackerWon ? 'Estes recursos foram retirados do teu castelo quando o ataque terminou.' : 'O atacante não conseguiu levar recursos.'}</small>
        </section>
        <p class="battle-report-message">${data.defenderWon ? 'As tuas tropas defenderam o castelo e obrigaram os sobreviventes inimigos a regressar.' : 'As defesas foram vencidas. Consulta os detalhes para veres onde o inimigo abriu brechas.'}</p>
      </div>`,
      `<button class="secondary-btn" data-action="modal-close">Fechar</button>
       <button class="action-btn" data-action="defense-battle-report-details" data-report-id="${context.escapeHtml(report.id)}">📋 Detalhes</button>`
    );
    document.querySelector('.modal')?.classList.add('battle-report-modal', 'defense-battle-report-modal');
  }

  function sectorCard(flank, data, context) {
    const troopMeta = context.getTroopsMeta?.() || {};
    const attack = data.attackBySector?.[flank.id] || {};
    const initial = data.defenseInitial?.[flank.id] || {};
    const final = data.defenseFinal?.[flank.id] || {};
    const attackersSent = cloneTroops(attack.sent, troopMeta);
    const attackersAfterWall = cloneTroops(attack.wallSurvivors, troopMeta);
    const defendersInitial = cloneTroops(initial.units, troopMeta);
    const defendersFinal = cloneTroops(final.units, troopMeta);
    const attackersLost = troopDifference(attackersSent, attackersAfterWall, troopMeta);
    const defendersLost = troopDifference(defendersInitial, defendersFinal, troopMeta);
    const breached = data.breachedFlanks.includes(flank.id);
    const used = data.usedFlanks.includes(flank.id);

    return `<article class="battle-sector-card defense-sector ${breached ? 'breached' : ''} ${used ? 'used' : 'unused'}">
      <header><span>${flank.icon}</span><h4>${context.escapeHtml(flank.name)}</h4><b>${!used ? 'Não atacado' : breached ? 'Brecha inimiga' : 'Defesa resistiu'}</b></header>
      <div class="battle-fort-bonuses">
        <span>🧱 +${context.format(initial.wallBonus || 0)}%</span>
        ${initial.gateBonus ? `<span>🚪 +${context.format(initial.gateBonus)}%</span>` : ''}
        <span>🏹 +${context.format(initial.rangedBonus || 0)}%</span>
      </div>
      <div class="battle-sector-tools">${toolChips(attack.toolsUsed, context)}${totalTools(attack.toolsUsed) ? `<small>Reduções sofridas: muralha −${context.format(attack.toolReductions?.wall || 0)}% · portão −${context.format(attack.toolReductions?.gate || 0)}% · distância −${context.format(attack.toolReductions?.ranged || 0)}%</small>` : ''}</div>
      <div class="battle-sector-versus">
        <div class="battle-side attack-side"><h5>Atacante</h5><div class="battle-sector-total">${context.format(totalTroops(attackersSent))}</div><div class="battle-chip-row">${troopChips(attackersSent, context)}</div><small>Baixas: ${context.format(totalTroops(attackersLost))}</small><small>Passaram: ${context.format(totalTroops(attackersAfterWall))}</small></div>
        <div class="battle-sector-arrow">⚔️</div>
        <div class="battle-side defense-side"><h5>Tua defesa</h5><div class="battle-sector-total">${context.format(totalTroops(defendersInitial))}</div><div class="battle-chip-row">${troopChips(defendersInitial, context)}</div><small>Baixas: ${context.format(totalTroops(defendersLost))}</small><small>Restantes: ${context.format(totalTroops(defendersFinal))}</small></div>
      </div>
    </article>`;
  }

  function openDetails(context, reportId) {
    const report = findReport(context, reportId);
    if (!report?.defenseBattleData) return;
    const data = report.defenseBattleData;
    const courtyardAttackers = data.courtyard.attackersEntered;
    const courtyardSurvivors = data.courtyard.attackersSurvived;
    const courtyardLosses = troopDifference(courtyardAttackers, courtyardSurvivors, context.getTroopsMeta?.());
    const defense = defenseTotals(data);
    const bonusPercent = Math.round((Number(data.courtyardBonus) || 0) * 100);

    context.openModal(
      `Detalhes da defesa — ${context.escapeHtml(data.attackerName)}`,
      `<div class="battle-details-sheet defense-details-sheet">
        <header class="battle-details-head">
          <div><small>Atacante</small><b>${context.escapeHtml(data.attackerName)} • Nv. ${context.format(data.attackerLevel)}</b></div>
          <div><small>Origem</small><b>X ${data.originCoordinates.x} • Y ${data.originCoordinates.y}</b></div>
          <div><small>Teu castelo</small><b>X ${data.coordinates.x} • Y ${data.coordinates.y}</b></div>
          <div class="battle-detail-outcome ${data.defenderWon ? 'victory' : 'defeat'}">${data.defenderWon ? 'Defesa vitoriosa' : 'Defesa derrotada'}</div>
        </header>
        <div class="battle-detail-sectors">${FLANKS.map(flank => sectorCard(flank, data, context)).join('')}</div>
        <section class="battle-courtyard-card ${data.defenderWon ? 'victory' : 'defeat'}">
          <header><h4>Combate no pátio</h4><span>Bónus inimigo de flancos: ${bonusPercent >= 0 ? '+' : ''}${bonusPercent}%</span></header>
          <div class="battle-courtyard-versus">
            <div><small>Atacantes que entraram</small><b>${context.format(totalTroops(courtyardAttackers))}</b><div class="battle-chip-row">${troopChips(courtyardAttackers, context)}</div><span>Baixas inimigas no pátio: ${context.format(totalTroops(courtyardLosses))}</span></div>
            <div class="battle-courtyard-result">${data.defenderWon ? '🛡️' : '🔥'}<strong>${data.defenderWon ? 'Pátio defendido' : 'Pátio conquistado pelo inimigo'}</strong></div>
            <div><small>Força da tua defesa</small><b>${context.format(data.courtyard.defensePower)}</b><span>Defensores antes: ${context.format(data.courtyard.defendersBefore)}</span><span>Defensores depois: ${context.format(data.courtyard.defendersAfter)}</span></div>
          </div>
        </section>
        <details class="battle-full-breakdown">
          <summary>Ver totais completos</summary>
          <div class="battle-breakdown-grid">
            <section><h4>Tropas inimigas enviadas</h4>${troopRows(data.troopsSent, context)}</section>
            <section><h4>Tropas inimigas sobreviventes</h4>${troopRows(data.troopsSurvived, context)}</section>
            <section><h4>Ferramentas inimigas consumidas</h4><div class="battle-tools-breakdown">${toolChips(data.toolsUsed, context)}</div></section>
            <section><h4>Tua defesa</h4><div class="battle-troop-row"><span>Defensores no início</span><b>${context.format(defense.initial)}</b></div><div class="battle-troop-row"><span>Defensores restantes</span><b>${context.format(defense.final)}</b></div><div class="battle-troop-row"><span>Baixas</span><b>${context.format(defense.lost)}</b></div></section>
          </div>
        </details>
      </div>`,
      `<button class="secondary-btn" data-action="defense-battle-report-open" data-report-id="${context.escapeHtml(report.id)}">← Voltar ao relatório</button>
       <button class="action-btn" data-action="modal-close">Concluir</button>`
    );
    document.querySelector('.modal')?.classList.add('battle-details-modal', 'defense-battle-details-modal');
  }

  function reportPresentation(report, context) {
    if (report?.reportType !== REPORT_TYPE || !report.defenseBattleData) return null;
    const data = report.defenseBattleData;
    return {
      label: data.defenderWon ? 'Defesa vitoriosa' : 'Castelo saqueado',
      className: data.defenderWon ? 'report-win' : 'report-loss',
      detailsHtml: `<div class="battle-report-table-summary defense-report-table-summary">${context.escapeHtml(report.text)}<small>${data.attackerWon ? `Recursos roubados: ${resourceLine(data.loot, context)}` : 'Nenhum recurso foi roubado.'}</small></div><button class="report-open-btn battle-report-open-btn" data-action="defense-battle-report-open" data-report-id="${context.escapeHtml(report.id)}">Abrir relatório</button>`
    };
  }

  async function handleAction(action, actionElement, context) {
    if (action === 'defense-battle-report-open') {
      openSummary(context, actionElement.dataset.reportId);
      return true;
    }
    if (action === 'defense-battle-report-details') {
      openDetails(context, actionElement.dataset.reportId);
      return true;
    }
    return false;
  }

  globalThis.ReinosDefenderBattleReports = Object.freeze({
    REPORT_TYPE,
    REPORT_VERSION,
    create,
    openSummary,
    openDetails,
    reportPresentation,
    handleAction
  });
})();
