'use strict';

(() => {
  const VERSION = 3;
  const LAYOUT_VERSION = 1;
  const GRID_SIZE = globalThis.ReinosCastleExpansions?.GRID_SIZE || 60;
  const OLD_GRID_SIZE = 20;
  const GRID_VERSION = 2;
  const TILE_SIZE = 48;
  const MAX_EXPANSION = globalThis.ReinosCastleExpansions?.MAX_EXPANSIONS || 16;

  const BUILDING_SIZES = {
    keep: [3, 3],
    woodcutter: [2, 2],
    quarry: [2, 2],
    farm: [2, 2],
    house: [2, 2],
    barracks: [2, 2],
    warehouse: [2, 2],
    marketplace: [2, 2],
    workshop: [2, 2],
    stables: [2, 2],
    hospital: [2, 2],
    tavern: [2, 2],
    watchtower: [1, 1],
    decoration: [1, 1]
  };

  const CATEGORIES = {
    economy: { name: 'Economia', icon: globalThis.ReinosResourceIcons?.icon?.('food') || 'Economia', types: ['woodcutter', 'quarry', 'farm', 'house', 'warehouse', 'marketplace'] },
    military: { name: 'Militares', icon: '⚔️', types: ['barracks', 'workshop', 'stables', 'hospital', 'tavern'] },
    defense: { name: 'Defesa', icon: '🛡️', types: ['watchtower'] },
    decoration: { name: 'Decorações', icon: '🌳', types: ['decoration'] }
  };

  const INITIAL_LAYOUT = {
    keep: [[28, 28]],
    woodcutter: [[25, 25], [25, 33]],
    quarry: [[33, 25], [33, 33]],
    farm: [[25, 30], [33, 30]],
    barracks: [[30, 25]],
    warehouse: [[30, 33]],
    house: [[25, 28], [33, 28]],
    marketplace: [[28, 25]],
    workshop: [[31, 25]],
    stables: [[25, 32]],
    hospital: [[33, 32]],
    tavern: [[28, 33]],
    watchtower: [[24, 24], [35, 24], [24, 35], [35, 35]],
    decoration: [[27, 25], [32, 25], [27, 34], [32, 34]]
  };

  let movingBuildingId = null;
  let pendingBuildSlot = null;

  function slotToPosition(slot) {
    const value = Math.max(0, Math.floor(Number(slot) || 0));
    return { x: value % GRID_SIZE, y: Math.floor(value / GRID_SIZE) };
  }

  function positionToSlot(x, y) {
    return Math.floor(y) * GRID_SIZE + Math.floor(x);
  }

  function sizeFor(type) {
    const [w, h] = BUILDING_SIZES[type] || [2, 2];
    return { w, h };
  }

  function boundsFor(profile) {
    return globalThis.ReinosCastleExpansions?.bounds?.(profile) || {
      min: 20, max: 39, minX: 20, minY: 20, maxX: 39, maxY: 39, width: 20, height: 20, size: 20, area: 400
    };
  }

  function ensureState(profile) {
    if (!profile) return false;
    let changed = false;
    if (!profile.castleState || typeof profile.castleState !== 'object') {
      profile.castleState = {
        version: VERSION,
        expansionLevel: 0,
        wallLevel: 1,
        gateLevel: 1,
        towerLevel: 1,
        layoutVersion: 0
      };
      changed = true;
    }

    const state = profile.castleState;

    if (Number(state.gridVersion) !== GRID_VERSION) {
      for (const building of profile.buildings || []) {
        const legacySlot = Math.max(0, Math.floor(Number(building.slot) || 0));
        const legacyX = legacySlot % OLD_GRID_SIZE;
        const legacyY = Math.floor(legacySlot / OLD_GRID_SIZE);
        if (legacyX < OLD_GRID_SIZE && legacyY < OLD_GRID_SIZE) {
          building.slot = (legacyY + 20) * GRID_SIZE + (legacyX + 20);
        }
      }
      state.gridVersion = GRID_VERSION;
      state.camera = { ...(state.camera || {}), zoom: 0.72, scrollLeft: null, scrollTop: null };
      changed = true;
    }

    if (globalThis.ReinosCastleExpansions?.normalizeState?.(profile)) changed = true;
    state.version = VERSION;
    state.expansionLevel = globalThis.ReinosCastleExpansions?.purchasedIds?.(profile)?.size ?? Math.max(0, Math.min(MAX_EXPANSION, Number(state.expansionLevel) || 0));
    state.wallLevel = Math.max(1, Number(state.wallLevel) || 1);
    state.gateLevel = Math.max(1, Number(state.gateLevel) || 1);
    state.towerLevel = Math.max(1, Number(state.towerLevel) || 1);

    if (state.layoutVersion !== LAYOUT_VERSION) {
      migrateLayout(profile);
      state.layoutVersion = LAYOUT_VERSION;
      changed = true;
    }

    return changed;
  }

  function migrateLayout(profile) {
    const counters = {};
    const occupied = [];
    const buildings = [...(profile.buildings || [])].sort((a, b) => (a.type === 'keep' ? -1 : b.type === 'keep' ? 1 : 0));

    for (const building of buildings) {
      const options = INITIAL_LAYOUT[building.type] || [];
      const index = counters[building.type] || 0;
      counters[building.type] = index + 1;
      let position = options[index] ? { x: options[index][0], y: options[index][1] } : null;

      if (!position || collidesPosition(occupied, building.type, position.x, position.y)) {
        position = findEmptyPositionInternal(profile, building.type, occupied, building.id) || { x: 20, y: 20 };
      }

      building.slot = positionToSlot(position.x, position.y);
      occupied.push({ id: building.id, type: building.type, slot: building.slot });
    }
  }

  function rectFor(type, slot) {
    const position = slotToPosition(slot);
    const size = sizeFor(type);
    return { x: position.x, y: position.y, w: size.w, h: size.h };
  }

  function rectanglesOverlap(a, b) {
    return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;
  }

  function collidesPosition(buildings, type, x, y, ignoreId = null) {
    const candidate = { x, y, ...sizeFor(type) };
    return buildings.some(building => {
      if (ignoreId && building.id === ignoreId) return false;
      return rectanglesOverlap(candidate, rectFor(building.type, building.slot));
    });
  }

  function isInsideUnlocked(profile, type, slot) {
    const rect = rectFor(type, slot);
    if (globalThis.ReinosCastleExpansions?.isRectUnlocked) {
      return globalThis.ReinosCastleExpansions.isRectUnlocked(profile, rect.x, rect.y, rect.w, rect.h);
    }
    const bounds = boundsFor(profile);
    return rect.x >= bounds.minX && rect.y >= bounds.minY && rect.x + rect.w - 1 <= bounds.maxX && rect.y + rect.h - 1 <= bounds.maxY;
  }

  function canPlace(profile, type, slot, ignoreId = null) {
    ensureState(profile);
    const rect = rectFor(type, slot);
    if (rect.x < 0 || rect.y < 0 || rect.x + rect.w > GRID_SIZE || rect.y + rect.h > GRID_SIZE) return false;
    if (!isInsideUnlocked(profile, type, slot)) return false;
    return !collidesPosition(profile.buildings || [], type, rect.x, rect.y, ignoreId);
  }

  function centerSpiral(profile) {
    const positions = globalThis.ReinosCastleExpansions?.cells?.(profile) || [];
    const center = (GRID_SIZE - 1) / 2;
    return positions.map(position => ({ ...position, d: Math.abs(position.x - center) + Math.abs(position.y - center) }))
      .sort((a, b) => a.d - b.d || a.y - b.y || a.x - b.x);
  }

  function findEmptyPositionInternal(profile, type, buildings = profile.buildings || [], ignoreId = null) {
    const size = sizeFor(type);
    for (const position of centerSpiral(profile)) {
      if (position.x + size.w > GRID_SIZE || position.y + size.h > GRID_SIZE) continue;
      if (!globalThis.ReinosCastleExpansions?.isRectUnlocked?.(profile, position.x, position.y, size.w, size.h)) continue;
      if (!collidesPosition(buildings, type, position.x, position.y, ignoreId)) return position;
    }
    return null;
  }

  function firstEmptySlot(profile, type = 'decoration', ignoreId = null) {
    ensureState(profile);
    const pos = findEmptyPositionInternal(profile, type, profile.buildings || [], ignoreId);
    return pos ? positionToSlot(pos.x, pos.y) : -1;
  }

  function publicOrder(profile) {
    ensureState(profile);
    let value = 100;
    for (const building of profile.buildings || []) {
      const level = Math.max(1, Number(building.level) || 1);
      if (building.type === 'decoration') value += 35 * level;
      if (building.type === 'house') value -= 10 * level;
      if (building.status === 'burning') value -= 25 * level;
    }
    value += (profile.castleState.expansionLevel || 0) * 8;
    return Math.max(0, Math.round(value));
  }

  function productivityMultiplier(profile) {
    const order = publicOrder(profile);
    return Math.max(0.65, Math.min(1.6, 1 + (order - 100) / 400));
  }

  function expansionCost(profile) {
    const prices = globalThis.ReinosCastleExpansions?.cost?.(profile);
    return prices?.resources || { wood: 2400, stone: 2900 };
  }

  function fortificationCost(kind, profile) {
    ensureState(profile);
    const key = `${kind}Level`;
    const level = profile.castleState[key] || 1;
    const base = kind === 'wall' ? 1600 : kind === 'gate' ? 1900 : 2100;
    return {
      wood: Math.round(base * Math.pow(1.65, level - 1)),
      stone: Math.round(base * 1.25 * Math.pow(1.7, level - 1)),
      coins: Math.round(500 * Math.pow(1.55, level - 1))
    };
  }

  function renderBuilding(building, ctx) {
    const defs = ctx.getBuildingsMeta();
    const def = defs[building.type] || { name: building.type, icon: '🏠' };
    const position = slotToPosition(building.slot);
    const size = sizeFor(building.type);
    const queue = ctx.getProfile().constructionQueue.find(item => item.buildingId === building.id);
    const levelClass = `castle-building-level-${Math.min(10, Math.max(1, building.level || 1))}`;
    const statusClass = building.status === 'burning' ? 'is-burning' : building.status === 'constructing' || building.status === 'upgrading' ? 'is-building' : '';
    const smoke = ['woodcutter', 'quarry', 'farm', 'house', 'barracks', 'workshop', 'stables', 'hospital', 'tavern'].includes(building.type)
      ? '<span class="castle-smoke castle-smoke-a"></span><span class="castle-smoke castle-smoke-b"></span>' : '';
    const flag = building.type === 'keep' ? '<span class="castle-flag"></span>' : '';
    const supportsIllustrated = ['keep','woodcutter','quarry','farm','house','barracks','warehouse','marketplace','workshop','stables','hospital','tavern','watchtower','decoration'].includes(building.type);
    const illustratedArt = globalThis.ReinosIllustratedBuildings?.castleArt?.(building)
      || (supportsIllustrated
        ? `<span class="castle-building-art illustrated-building-art"><img class="illustrated-building-image illustrated-building-image-castle" src="${globalThis.ReinosIllustratedBuildings?.assetFor?.(building.type, building.level || 1) || ('../assets/buildings/levels/' + building.type + '/level_01.png')}" alt="${ctx.escapeHtml(def.name)} — nível ${building.level || 1}" draggable="false" /></span>`
        : '');
    const buildingArt = illustratedArt
      || globalThis.ReinosBuildingVisuals?.castleArt?.(building, def.icon)
      || globalThis.ReinosBarracksVisuals?.castleArt?.(building, def.icon)
      || `<span class="castle-building-art"><span class="castle-building-icon">${def.icon}</span></span>`;
    const illustratedClass = illustratedArt ? 'has-illustrated-building-art' : '';
    return `<button class="castle-building castle-building-${building.type} ${illustratedClass} ${levelClass} ${statusClass}" data-action="building-open" data-id="${building.id}" style="--cx:${position.x};--cy:${position.y};--cw:${size.w};--ch:${size.h}" title="${ctx.escapeHtml(def.name)} — Nível ${building.level || 1}">
      <span class="castle-building-click-zone" data-action="building-open" data-id="${building.id}" title="${ctx.escapeHtml(def.name)} — Nível ${building.level || 1}" aria-label="${ctx.escapeHtml(def.name)} — Nível ${building.level || 1}"></span>
      <span class="castle-building-shadow"></span>${smoke}${flag}
      ${buildingArt}
      <span class="castle-building-label"><strong>${ctx.escapeHtml(def.name)}</strong><em>Nv. ${building.level || 1}</em></span>
      ${queue ? `<span class="castle-building-timer" data-countdown="${queue.endAt}">${ctx.formatTime(queue.endAt - ctx.now())}</span>` : ''}
    </button>`;
  }

  function renderTerrain(profile) {
    const tiles = [];
    const occupiedStarts = new Set((profile.buildings || []).map(building => building.slot));
    for (let y = 0; y < GRID_SIZE; y++) {
      for (let x = 0; x < GRID_SIZE; x++) {
        const unlocked = globalThis.ReinosCastleExpansions?.isCellUnlocked?.(profile, x, y) ?? false;
        if (!unlocked) continue;
        const slot = positionToSlot(x, y);
        const occupied = occupiedStarts.has(slot);
        tiles.push(`<button class="castle-ground-tile unlocked ${occupied ? 'occupied-start' : ''}" data-action="build-slot" data-slot="${slot}" data-grid-x="${x}" data-grid-y="${y}" style="--tx:${x};--ty:${y}" aria-label="Parcela X ${x} Y ${y}"><span>＋</span></button>`);
      }
    }
    return tiles.join('');
  }

  function renderDecorations(bounds) {
    const start = bounds.min * TILE_SIZE;
    const end = (bounds.max + 1) * TILE_SIZE;
    const center = (start + end) / 2;
    return `
      <div class="castle-wall castle-wall-top" style="left:${start}px;top:${start - 14}px;width:${end - start}px"></div>
      <div class="castle-wall castle-wall-bottom" style="left:${start}px;top:${end - 3}px;width:${end - start}px"></div>
      <div class="castle-wall castle-wall-left" style="left:${start - 14}px;top:${start}px;height:${end - start}px"></div>
      <div class="castle-wall castle-wall-right" style="left:${end - 3}px;top:${start}px;height:${end - start}px"></div>
      <div class="castle-tower tower-nw" style="left:${start - 27}px;top:${start - 27}px"></div>
      <div class="castle-tower tower-ne" style="left:${end - 25}px;top:${start - 27}px"></div>
      <div class="castle-tower tower-sw" style="left:${start - 27}px;top:${end - 25}px"></div>
      <div class="castle-tower tower-se" style="left:${end - 25}px;top:${end - 25}px"></div>
      <button class="castle-gate" data-action="castle-fortification-open" style="left:${center - 42}px;top:${end - 13}px" title="Muralha, portão e torres"><span>⚔</span></button>
      <span class="castle-inhabitant inhabitant-a" style="left:${center - 130}px;top:${center + 88}px">🚶</span>
      <span class="castle-inhabitant inhabitant-b" style="left:${center + 100}px;top:${center - 70}px">🧑‍🌾</span>
      <span class="castle-inhabitant inhabitant-c" style="left:${center - 10}px;top:${center + 145}px">🛒</span>
      <span class="castle-bird bird-a" style="left:${center - 210}px;top:${start - 70}px">⌁</span>
      <span class="castle-bird bird-b" style="left:${center + 180}px;top:${start - 50}px">⌁</span>`;
  }

  function render(ctx) {
    const profile = ctx.getProfile();
    ensureState(profile);
    const bounds = boundsFor(profile);
    const order = publicOrder(profile);
    const productivity = productivityMultiplier(profile);
    const maxed = profile.castleState.expansionLevel >= MAX_EXPANSION;
    const moveNotice = movingBuildingId ? `<div class="castle-mode-banner">Arrasta o edifício selecionado para uma zona livre. <button data-action="castle-move-cancel">Cancelar</button></div>` : '';

    const isoScene = globalThis.ReinosCastleIsometricView?.renderScene?.({
      profile,
      ctx,
      bounds,
      gridSize: GRID_SIZE,
      helpers: { slotToPosition, positionToSlot, sizeFor, gridSize: GRID_SIZE }
    });
    const fallbackScene = `<div class="castle-world-shell">
      <div class="castle-world-viewport" id="castle-world-viewport">
        <div class="castle-world" style="--castle-grid:${GRID_SIZE};--castle-tile:${TILE_SIZE}px">
          <div class="castle-ground"></div><div class="castle-river"></div>
          <div class="castle-road road-a"></div><div class="castle-road road-b"></div>
          ${renderTerrain(profile)}${renderDecorations(bounds)}
          ${(profile.buildings || []).map(building => renderBuilding(building, ctx)).join('')}
        </div>
      </div>
      <div class="castle-legend"><b>Controlos</b><span>Arrasta o terreno para percorrer o castelo</span><span>Usa o botão Construir para adicionar edifícios</span><span>Clica num edifício para melhorar, mover ou demolir</span><span>Expande a muralha para ganhar novas parcelas</span></div>
    </div>`;

    ctx.getContent().innerHTML = `<div class="view castle-view">
      ${ctx.viewHeader('O teu castelo', 'Desenvolve o povoado desde uma pequena fortaleza até uma grande cidadela.')}
      <div class="castle-stat-strip">
        <div><span>🏰 Área desbloqueada</span><strong>${ctx.format(globalThis.ReinosCastleExpansions?.unlockedArea?.(profile) || bounds.area || 400)} / 3 600</strong></div>
        <div><span>🌿 Ordem pública</span><strong>${ctx.format(order)}</strong></div>
        <div><span>⚙️ Produtividade</span><strong>${Math.round(productivity * 100)}%</strong></div>
        <div><span>🧱 Muralha</span><strong>Nv. ${profile.castleState.wallLevel}</strong></div>
        <div><span>🚪 Portão</span><strong>Nv. ${profile.castleState.gateLevel}</strong></div>
      </div>
      ${moveNotice}
      ${isoScene?.html || fallbackScene}
    </div>`;

    requestAnimationFrame(() => {
      const activated = isoScene && globalThis.ReinosCastleIsometricView?.activate?.({ profile, ctx, center: isoScene.center });
      if (!activated) centerViewport(ctx);
      globalThis.ReinosCastleGridPlacement?.mount?.({ profile, ctx });
    });
    return true;
  }

  function centerViewport(ctx) {
    const viewport = document.querySelector('#castle-world-viewport');
    if (!viewport) return;
    const profile = ctx.getProfile();
    const keep = profile.buildings.find(building => building.type === 'keep');
    const pos = keep ? slotToPosition(keep.slot) : { x: 9, y: 9 };
    viewport.scrollLeft = Math.max(0, pos.x * TILE_SIZE - viewport.clientWidth / 2 + TILE_SIZE * 1.5);
    viewport.scrollTop = Math.max(0, pos.y * TILE_SIZE - viewport.clientHeight / 2 + TILE_SIZE * 1.5);
  }

  function openBuildModal(slot, ctx) {
    const profile = ctx.getProfile();
    ensureState(profile);
    if (profile.constructionQueue.length >= ctx.constructionQueueLimit()) {
      ctx.toast('A fila de construção está ocupada.', 'error');
      return true;
    }
    pendingBuildSlot = Number(slot);
    const defs = ctx.getBuildingsMeta();
    const keepLevel = ctx.getKeepLevel();
    const categoryHtml = Object.entries(CATEGORIES).map(([categoryId, category]) => {
      const choices = category.types.filter(type => defs[type]).map(type => {
        const def = defs[type];
        const maxed = def.max && ctx.buildingCount(type) >= def.max;
        const keepLocked = (def.keepRequired || 1) > keepLevel;
        const noSpace = firstEmptySlot(profile, type) < 0;
        const cost = ctx.buildingCost(type, 1);
        const size = sizeFor(type);
        let buttonText = 'Selecionar';
        if (maxed) buttonText = 'Limite atingido';
        else if (keepLocked) buttonText = `Fortaleza Nv. ${def.keepRequired}`;
        else if (noSpace) buttonText = 'Sem espaço disponível';
        return `<div class="castle-build-choice">
          <div class="castle-build-choice-icon">${def.icon}</div>
          <div class="castle-build-choice-main"><strong>${ctx.escapeHtml(def.name)}</strong><small>${ctx.escapeHtml(def.description)}</small><div class="costs">${ctx.costsHtml(cost)}</div><span>⏱ ${ctx.formatTime(ctx.buildingTime(type, 1))} · Ocupa ${size.w}×${size.h} quadrados</span></div>
          <button class="action-btn" data-action="castle-build-placement-start" data-type="${type}" ${maxed || keepLocked || noSpace ? 'disabled' : ''}>${buttonText}</button>
        </div>`;
      }).join('');
      return `<section class="castle-build-category"><h4>${category.icon} ${category.name}</h4>${choices}</section>`;
    }).join('');
    ctx.openModal('Menu de construção', `<div class="castle-build-menu"><p>Escolhe um edifício. Depois arrasta-o sobre a grelha e confirma a posição.</p>${categoryHtml}</div>`, '<button class="secondary-btn" data-action="modal-close">Fechar</button>');
    return true;
  }

  function escapeAttr(value) {
    return String(value ?? '').replace(/[&<>"']/g, char => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[char]));
  }

  function buildingModalMoveButton(building) {
    if (!building) return '';
    return `<button class="secondary-btn" data-action="castle-move-start" data-id="${escapeAttr(building.id)}">Mover</button>`;
  }

  function openExpansionModal(ctx) {
    const profile = ctx.getProfile();
    ensureState(profile);
    if (profile.castleState.expansionLevel >= MAX_EXPANSION) return ctx.toast('O castelo já atingiu a área máxima de 60 × 60 quadrados.', 'error');
    const html = globalThis.ReinosCastleExpansions?.modalHtml?.(profile, ctx);
    if (!html) return ctx.toast('O sistema de expansões não está disponível.', 'error');
    ctx.openModal('Expansões do castelo', html, '<button class="secondary-btn" data-action="modal-close">Fechar</button>');
    document.querySelector('.modal')?.classList.add('castle-expansion-modal');
  }

  function openFortificationModal(ctx) {
    const profile = ctx.getProfile();
    ensureState(profile);
    const rows = [
      ['wall', '🧱', 'Muralha', profile.castleState.wallLevel, 'Melhora a defesa dos flancos.'],
      ['gate', '🚪', 'Portão', profile.castleState.gateLevel, 'Melhora a defesa da frente.'],
      ['tower', '🗼', 'Torres', profile.castleState.towerLevel, 'Aumenta a capacidade defensiva.']
    ].map(([kind, icon, name, level, description]) => {
      const comparison = globalThis.ReinosBuildingUpgradeBenefits?.fortificationComparisonHtml?.(kind, level, { format: ctx.format, escapeHtml: ctx.escapeHtml }) || '';
      return `<div class="castle-fortification-row"><span class="castle-fortification-icon">${icon}</span><div class="castle-fortification-main"><strong>${name} — Nível ${level}</strong><small>${description}</small>${comparison}<div class="costs">${ctx.costsHtml(fortificationCost(kind, profile))}</div></div><button class="action-btn" data-action="castle-fortification-upgrade" data-kind="${kind}">Melhorar</button></div>`;
    }).join('');
    ctx.openModal('Defesas do castelo', `<div class="castle-fortification-list">${rows}</div>`, '<button class="secondary-btn" data-action="modal-close">Fechar</button>');
    document.querySelector('.modal')?.classList.add('castle-fortification-modal');
  }

  function handleAction(action, element, ctx) {
    const profile = ctx.getProfile();
    if (!profile) return false;
    ensureState(profile);

    if (action === 'castle-build-placement-start') {
      const type = String(element.dataset.type || '');
      const def = ctx.getBuildingsMeta()[type];
      if (!def) return true;
      if (profile.constructionQueue.length >= ctx.constructionQueueLimit()) return ctx.toast('A fila de construção está ocupada.', 'error'), true;
      if (def.max && ctx.buildingCount(type) >= def.max) return ctx.toast('Atingiste o limite deste edifício.', 'error'), true;
      if ((def.keepRequired || 1) > ctx.getKeepLevel()) return ctx.toast(`Necessitas da Fortaleza no nível ${def.keepRequired}.`, 'error'), true;
      if (firstEmptySlot(profile, type) < 0) return ctx.toast('Não existe espaço livre suficiente para este edifício.', 'error'), true;
      if (!ctx.canAfford(ctx.buildingCost(type, 1))) return ctx.toast('Não tens recursos suficientes.', 'error'), true;
      ctx.closeModal();
      if (!globalThis.ReinosCastleGridPlacement?.beginBuild?.(type, profile, ctx)) {
        ctx.toast('Não foi possível iniciar a colocação do edifício.', 'error');
      }
      return true;
    }
    if (action === 'castle-expand') {
      openExpansionModal(ctx);
      return true;
    }
    if (action === 'castle-expansion-select') {
      const id = String(element.dataset.expansionId || '');
      const html = globalThis.ReinosCastleExpansions?.purchaseHtml?.(profile, id, ctx);
      if (!html) return ctx.toast('Esta expansão ainda não está disponível.', 'error'), true;
      ctx.openModal('Comprar expansão', html, '<button class="secondary-btn" data-action="castle-expand">Voltar</button><button class="secondary-btn" data-action="modal-close">Cancelar</button>');
      document.querySelector('.modal')?.classList.add('castle-expansion-purchase-modal');
      return true;
    }
    if (action === 'castle-expansion-buy') {
      const id = String(element.dataset.expansionId || '');
      const payment = String(element.dataset.payment || 'resources');
      if (!globalThis.ReinosCastleExpansions?.isAvailable?.(profile, id)) return ctx.toast('Esta expansão já não está disponível.', 'error'), true;
      const prices = globalThis.ReinosCastleExpansions.cost(profile);
      const selectedCost = payment === 'crowns' ? prices.crowns : prices.resources;
      if (!ctx.canAfford(selectedCost)) return ctx.toast(payment === 'crowns' ? 'Não tens coroas suficientes.' : 'Não tens madeira e pedra suficientes.', 'error'), true;
      ctx.spend(selectedCost);
      if (!globalThis.ReinosCastleExpansions.purchase(profile, id)) return ctx.toast('Não foi possível adquirir esta expansão.', 'error'), true;
      ctx.closeModal();
      ctx.renderGame();
      ctx.persist(true);
      ctx.toast('Expansão adquirida imediatamente. Uma nova área de 10 × 20 e um espaço de torre foram desbloqueados.', 'success');
      return true;
    }
    if (action === 'castle-expand-confirm') {
      const first = globalThis.ReinosCastleExpansions?.availablePlots?.(profile)?.[0];
      if (!first) return true;
      element.dataset.expansionId = first.id;
      element.dataset.payment = 'resources';
      return handleAction('castle-expansion-buy', element, ctx);
    }
    if (action === 'castle-fortification-open') {
      openFortificationModal(ctx);
      return true;
    }
    if (action === 'castle-fortification-upgrade') {
      const kind = String(element.dataset.kind || '');
      if (!['wall', 'gate', 'tower'].includes(kind)) return true;
      const cost = fortificationCost(kind, profile);
      if (!ctx.canAfford(cost)) return ctx.toast('Não tens recursos suficientes.', 'error'), true;
      ctx.spend(cost);
      profile.castleState[`${kind}Level`] += 1;
      ctx.closeModal();
      ctx.renderGame();
      ctx.persist(true);
      ctx.toast(`${kind === 'wall' ? 'Muralha' : kind === 'gate' ? 'Portão' : 'Torres'} melhorado.`, 'success');
      return true;
    }
    if (action === 'castle-move-start') {
      const building = profile.buildings.find(item => item.id === element.dataset.id);
      if (!building) return true;
      ctx.closeModal();
      globalThis.ReinosCastleGridPlacement?.armExisting?.(building.id, profile, ctx);
      return true;
    }
    if (action === 'castle-move-cancel') {
      movingBuildingId = null;
      ctx.renderActiveView();
      return true;
    }
    if (action === 'build-slot' && movingBuildingId) {
      const building = profile.buildings.find(item => item.id === movingBuildingId);
      const slot = Number(element.dataset.slot);
      if (!building) {
        movingBuildingId = null;
        return true;
      }
      if (!canPlace(profile, building.type, slot, building.id)) {
        ctx.toast('O edifício não cabe nessa posição.', 'error');
        return true;
      }
      building.slot = slot;
      movingBuildingId = null;
      ctx.renderActiveView();
      ctx.persist(true);
      ctx.toast('Edifício movido.', 'success');
      return true;
    }
    return false;
  }

  function defenseBonuses(profile) {
    ensureState(profile);
    return {
      wall: profile.castleState.wallLevel * 8,
      gate: profile.castleState.gateLevel * 10,
      capacity: profile.castleState.towerLevel * 12
    };
  }

  globalThis.ReinosCastleSystem = {
    VERSION,
    GRID_SIZE,
    TILE_SIZE,
    MAX_EXPANSION,
    ensureState,
    render,
    canPlace,
    firstEmptySlot,
    openBuildModal,
    buildingModalMoveButton,
    handleAction,
    publicOrder,
    productivityMultiplier,
    defenseBonuses,
    slotToPosition,
    positionToSlot,
    sizeFor,
    boundsFor,
    isInsideUnlocked,
    expansionCost
  };
})();
