// ─── Golem Helper Functions ──────────────────────────────────────────────
// Component-based construction system utilities.

import type { RuntimeActiveGolem } from '../../types';
import type {
  ComputedGolemStats,
  GolemDesign,
  GolemManaCost,
  GolemUnlockRequirement,
} from './types';
import { CORES } from './cores';
import { FRAMES } from './frames';
import { MIND_CIRCUITS } from './mindCircuits';

// ─── Golem Slots ──────────────────────────────────────────────────────────

/**
 * Get base golem slots from Fabricator attunement level.
 * Level 2 = 1, Level 4 = 2, Level 6 = 3, Level 8 = 4, Level 10 = 5
 */
export function getGolemSlots(fabricatorLevel: number): number {
  if (fabricatorLevel < 2) return 0;
  return Math.floor(fabricatorLevel / 2);
}

// ─── Unlock Checks ────────────────────────────────────────────────────────

/**
 * Check if a component is unlocked based on player state.
 */
export function isComponentUnlocked(
  requirement: GolemUnlockRequirement,
  attunements: Record<string, { active: boolean; level: number }>,
  unlockedElements: string[],
  signedGuardianPacts: number[],
): boolean {
  switch (requirement.type) {
    case 'attunement_level': {
      const attState = attunements[requirement.attunement || ''];
      return !!attState?.active && (attState.level || 1) >= (requirement.level || 1);
    }
    case 'mana_unlocked':
      return unlockedElements.includes(requirement.manaType || '');
    case 'dual_attunement': {
      if (!requirement.attunements || !requirement.levels) return false;
      return requirement.attunements.every((attId, idx) => {
        const att = attunements[attId];
        return att?.active && (att.level || 1) >= requirement.levels![idx];
      });
    }
    case 'guardian_pact': {
      // Requires dual attunement plus at least one guardian pact
      if (!requirement.attunements || !requirement.levels) return false;
      const attOk = requirement.attunements.every((attId, idx) => {
        const att = attunements[attId];
        return att?.active && (att.level || 1) >= requirement.levels![idx];
      });
      return attOk && signedGuardianPacts.length > 0;
    }
    default:
      return false;
  }
}

// ─── Computed Stats ───────────────────────────────────────────────────────

/**
 * Compute all derived stats for a golem design from its components.
 */
export function computeGolemStats(design: GolemDesign): ComputedGolemStats {
  const core = design.core;
  const frame = design.frame;
  const circuit = design.mindCircuit;
  const enchantments = design.enchantments;

  // Total summon cost from all components
  // For Guardian Core, use guardian-specific summon cost override if provided (spec §4.3)
  const coreSummonCost = core.id === 'guardian' && design.guardianSummonCost
    ? design.guardianSummonCost
    : core.summonCost;
  const totalSummonCost: GolemManaCost[] = [
    ...coreSummonCost,
    ...frame.summonCost,
    ...circuit.summonCost,
    ...enchantments.flatMap((e) => e.summonCost),
  ];

  // Player upkeep = Core.manaRegen × 2 per hour, split across all mana types (spec §13)
  // For Guardian Core, use guardian-specific primary mana type if provided (spec §4.3)
  const effectivePrimaryManaType = core.id === 'guardian' && design.guardianPrimaryManaType
    ? design.guardianPrimaryManaType
    : core.primaryManaType;
  const upkeepManaTypes = design.selectedManaTypes.length > 0
    ? design.selectedManaTypes
    : (core.id === 'guardian' && design.guardianPrimaryManaType
      ? [design.guardianPrimaryManaType]
      : core.manaTypes);
  const upkeepPerType = (core.manaRegen * 2) / Math.max(1, upkeepManaTypes.length);
  const upkeepCostPerHour: GolemManaCost[] = upkeepManaTypes.map((mt) => ({
    type: 'element' as const,
    element: mt,
    amount: upkeepPerType,
  }));

  // Enchantment capacity = Frame.MagicAffinity(%) × Core.TierMultiplier
  // magicAffinity is stored as decimal (0.3 = 30%) per spec §5.1, so multiply by 100
  const enchantmentCapacity = Math.round(frame.magicAffinity * 100) * core.tierMultiplier;

  return {
    maxRoomDuration: core.maxRoomDuration,
    totalSummonCost,
    upkeepCostPerHour,
    manaCapacity: core.manaCapacity,
    manaRegen: core.manaRegen,
    baseDamage: frame.baseDamage,
    attackSpeed: frame.attackSpeed,
    armorPierce: frame.armorPierce,
    magicAffinity: frame.magicAffinity,
    aoeTargets: frame.aoeTargets,
    spellSlots: circuit.spellSlots,
    availableManaTypes: design.selectedManaTypes.length > 0
      ? design.selectedManaTypes
      : core.manaTypes,
    enchantmentCapacity,
    specialEffect: frame.specialEffect,
  };
}

// ─── Summoning Cost Checks ────────────────────────────────────────────────

/**
 * Check if player can afford to summon a golem design.
 */
export function canAffordGolemDesign(
  design: GolemDesign,
  rawMana: number,
  elements: Record<string, { current: number; max: number; unlocked: boolean }>,
): { canAfford: boolean; missing: string } {
  const stats = computeGolemStats(design);

  for (const cost of stats.totalSummonCost) {
    if (cost.type === 'raw') {
      if (rawMana < cost.amount) {
        return { canAfford: false, missing: `raw mana (${cost.amount} needed)` };
      }
    } else if (cost.element) {
      const elem = elements[cost.element];
      if (!elem || !elem.unlocked) {
        return { canAfford: false, missing: `${cost.element} mana (not unlocked)` };
      }
      if (elem.current < cost.amount) {
        return { canAfford: false, missing: `${cost.element} mana (${cost.amount} needed, have ${elem.current})` };
      }
    }
  }

  return { canAfford: true, missing: '' };
}

// ─── Active Golem Helpers ─────────────────────────────────────────────────

/**
 * Create a new RuntimeActiveGolem from a GolemDesign for combat.
 */
export function createActiveGolem(
  design: GolemDesign,
  currentFloor: number,
): RuntimeActiveGolem {
  return {
    designId: design.id,
    summonedFloor: currentFloor,
    attackProgress: 0,
    roomsRemaining: design.core.maxRoomDuration,
    currentMana: design.core.manaCapacity,
    spellCastIndex: 0,
  };
}

// ─── Component Lookups ────────────────────────────────────────────────────

/** Get a CoreDefinition by ID */
export function getCore(id: string) {
  return CORES[id] || null;
}

/** Get a FrameDefinition by ID */
export function getFrame(id: string) {
  return FRAMES[id] || null;
}

/** Get a MindCircuitDefinition by ID */
export function getMindCircuit(id: string) {
  return MIND_CIRCUITS[id] || null;
}

