// ─── Regression Test: Issue #352 ──────────────────────────────────────────────
// Golem combat wipes all mana when no enemies are alive
//
// Bug: processGolemAttacks initialized rawMana=0 and elements={} as local
// accumulators. When no enemies were alive, processBasicAttack never called
// onDamageDealt, so these zero/empty values were returned. The caller in
// combat-actions.ts then overwrote the game's actual mana state with zeros.
//
// Fix: processGolemAttacks and processBasicAttack now accept currentRawMana
// and currentElements as parameters and initialize from them instead of 0/{}.

import { describe, it, expect } from 'vitest';
import { processGolemAttacks } from '../stores/golem-combat-actions';
import { processBasicAttack } from '../stores/golem-combat-helpers';
import type { EnemyState, RuntimeActiveGolem } from '../types';

// ─── Helpers ──────────────────────────────────────────────────────────────────

function makeEnemy(overrides: Partial<EnemyState> = {}): EnemyState {
  return {
    id: 'enemy-1',
    name: 'Test Enemy',
    hp: 0, // Dead enemy — this triggers the bug
    maxHP: 100,
    armor: 0.2,
    dodgeChance: 0,
    element: 'fire',
    activeEffects: [],
    effectiveArmor: 0.2,
    ...overrides,
  };
}

function makeAliveEnemy(overrides: Partial<EnemyState> = {}): EnemyState {
  return {
    id: 'enemy-1',
    name: 'Test Enemy',
    hp: 100,
    maxHP: 100,
    armor: 0.2,
    dodgeChance: 0,
    element: 'fire',
    activeEffects: [],
    effectiveArmor: 0.2,
    ...overrides,
  };
}

// ─── Tests ────────────────────────────────────────────────────────────────────

describe('Issue #352 — Golem combat mana wipe', () => {
  const testRawMana = 500;
  const testElements: Record<string, { current: number; max: number; unlocked: boolean }> = {
    fire: { current: 200, max: 500, unlocked: true },
    water: { current: 100, max: 500, unlocked: true },
  };

  describe('processBasicAttack preserves mana when no targets', () => {
    it('should return current rawMana (not 0) when no enemies are alive', () => {
      const result = processBasicAttack(
        {
          frame: { baseDamage: 10, armorPierce: 0.15, element: 'fire', aoeTargets: 1 },
          bonusArmorPierce: 0,
          enchantmentEffects: [],
          enemyElement: 'fire',
          getTargetEnemy: () => null, // No living target
          getTargetEnemies: () => [],
          onDamageDealt: () => ({ rawMana: testRawMana, elements: testElements }),
          applyDamageToRoom: () => ({ floorHP: 50, floorMaxHP: 100, roomCleared: false }),
          onApplyEnchantmentEffects: () => {},
        },
        testRawMana,
        testElements,
      );

      // rawMana should be preserved, not wiped to 0
      expect(result.rawMana).toBe(testRawMana);
    });

    it('should return current elements (not {}) when no enemies are alive', () => {
      const result = processBasicAttack(
        {
          frame: { baseDamage: 10, armorPierce: 0.15, element: 'fire', aoeTargets: 1 },
          bonusArmorPierce: 0,
          enchantmentEffects: [],
          enemyElement: 'fire',
          getTargetEnemy: () => null,
          getTargetEnemies: () => [],
          onDamageDealt: () => ({ rawMana: testRawMana, elements: testElements }),
          applyDamageToRoom: () => ({ floorHP: 50, floorMaxHP: 100, roomCleared: false }),
          onApplyEnchantmentEffects: () => {},
        },
        testRawMana,
        testElements,
      );

      // elements should be preserved, not wiped to {}
      expect(result.elements).toEqual(testElements);
    });

    it('should return current rawMana when AoE attack has no targets', () => {
      const result = processBasicAttack(
        {
          frame: { baseDamage: 10, armorPierce: 0.15, element: 'fire', aoeTargets: 3 },
          bonusArmorPierce: 0,
          enchantmentEffects: [],
          enemyElement: 'fire',
          getTargetEnemy: () => null,
          getTargetEnemies: () => [], // No living enemies for AoE
          onDamageDealt: () => ({ rawMana: 0, elements: {} }),
          applyDamageToRoom: () => ({ floorHP: 50, floorMaxHP: 100, roomCleared: false }),
          onApplyEnchantmentEffects: () => {},
        },
        testRawMana,
        testElements,
      );

      // When no targets for AoE, mana should be preserved
      expect(result.rawMana).toBe(testRawMana);
      expect(result.elements).toEqual(testElements);
    });
  });

  describe('processGolemAttacks preserves mana when no golems attack', () => {
    it('should return current rawMana when golem has no attack progress', () => {
      // Golem with attackProgress=0 won't enter the while loop
      const activeGolem: RuntimeActiveGolem = {
        designId: 'test_golem',
        summonedFloor: 1,
        attackProgress: 0, // Not ready to attack
        roomsRemaining: 3,
        currentMana: 50,
        spellCastIndex: 0,
      };

      const serializedDesign = {
        id: 'test_golem',
        name: 'Test Golem',
        coreId: 'basic',
        frameId: 'earth',
        mindCircuitId: 'simple',
        enchantmentIds: [],
        selectedManaTypes: [],
        selectedSpells: [],
      };

      const result = processGolemAttacks(
        [activeGolem],
        { test_golem: serializedDesign },
        () => ({ rawMana: 0, elements: {} }),
        () => ({ floorHP: 50, floorMaxHP: 100, roomCleared: false }),
        'fire',
        () => null,
        () => [],
        () => {},
        testRawMana,
        testElements,
      );

      // rawMana should be preserved, not wiped to 0
      expect(result.rawMana).toBe(testRawMana);
    });

    it('should return current elements when golem has no attack progress', () => {
      const activeGolem: RuntimeActiveGolem = {
        designId: 'test_golem',
        summonedFloor: 1,
        attackProgress: 0,
        roomsRemaining: 3,
        currentMana: 50,
        spellCastIndex: 0,
      };

      const serializedDesign = {
        id: 'test_golem',
        name: 'Test Golem',
        coreId: 'basic',
        frameId: 'earth',
        mindCircuitId: 'simple',
        enchantmentIds: [],
        selectedManaTypes: [],
        selectedSpells: [],
      };

      const result = processGolemAttacks(
        [activeGolem],
        { test_golem: serializedDesign },
        () => ({ rawMana: 0, elements: {} }),
        () => ({ floorHP: 50, floorMaxHP: 100, roomCleared: false }),
        'fire',
        () => null,
        () => [],
        () => {},
        testRawMana,
        testElements,
      );

      // elements should be preserved, not wiped to {}
      expect(result.elements).toEqual(testElements);
    });

    it('should return current rawMana when no active golems', () => {
      const result = processGolemAttacks(
        [], // No golems
        {},
        () => ({ rawMana: 0, elements: {} }),
        () => ({ floorHP: 50, floorMaxHP: 100, roomCleared: false }),
        'fire',
        () => null,
        () => [],
        () => {},
        testRawMana,
        testElements,
      );

      expect(result.rawMana).toBe(testRawMana);
      expect(result.elements).toEqual(testElements);
    });
  });

  describe('processGolemAttacks still works when enemies are alive', () => {
    it('should process damage and update mana when enemies are alive', () => {
      const aliveEnemy = makeAliveEnemy();
      const activeGolem: RuntimeActiveGolem = {
        designId: 'test_golem',
        summonedFloor: 1,
        attackProgress: 1.0,
        roomsRemaining: 3,
        currentMana: 50,
        spellCastIndex: 0,
      };

      const serializedDesign = {
        id: 'test_golem',
        name: 'Test Golem',
        coreId: 'basic',
        frameId: 'earth',
        mindCircuitId: 'simple',
        enchantmentIds: [],
        selectedManaTypes: [],
        selectedSpells: [],
      };

      const updatedElements = { fire: { current: 210, max: 500, unlocked: true } };

      const result = processGolemAttacks(
        [activeGolem],
        { test_golem: serializedDesign },
        () => ({ rawMana: testRawMana + 5, elements: updatedElements }),
        () => ({ floorHP: 50, floorMaxHP: 100, roomCleared: false }),
        'fire',
        () => aliveEnemy,
        () => [aliveEnemy],
        () => {},
        testRawMana,
        testElements,
      );

      // When enemies are alive, mana should be updated from onDamageDealt callback
      expect(result.rawMana).toBe(testRawMana + 5);
    });
  });
});
