import { describe, it, expect, beforeEach } from 'vitest';
import { useGameStore } from '../stores/gameStore';
import { useManaStore } from '../stores/manaStore';
import { useCombatStore } from '../stores/combatStore';
import { MAX_DAY } from '../constants';
import { getFloorMaxHP } from '../utils';
import { resetAllStores, tickN } from './cross-module-helpers';

describe('Cross-Module: Combat & Meditation', () => {
  beforeEach(resetAllStores);

  describe('combat floor clearing via tick', () => {
    it('should advance floor when climb action deals enough damage', () => {
      useManaStore.setState({ rawMana: 9999 });
      useCombatStore.setState({
        currentAction: 'climb',
        climbDirection: 'up',
        currentRoomIndex: 0,
        roomsPerFloor: 1,
        currentFloor: 1,
        floorHP: getFloorMaxHP(1),
        floorMaxHP: getFloorMaxHP(1),
        activeSpell: 'manaBolt',
      });

      tickN(500);

      expect(useCombatStore.getState().currentFloor).toBeGreaterThan(1);
      const { floorHP, floorMaxHP } = useCombatStore.getState();
      expect(floorHP).toBeGreaterThanOrEqual(0);
      expect(floorHP).toBeLessThanOrEqual(floorMaxHP);
    });

    it('should not advance floor when action is meditate', () => {
      useCombatStore.setState({
        currentAction: 'meditate',
        currentFloor: 1,
        floorHP: getFloorMaxHP(1),
        activeSpell: 'manaBolt',
      });

      tickN(50);

      expect(useCombatStore.getState().currentFloor).toBe(1);
      expect(useCombatStore.getState().maxFloorReached).toBe(1);
    });

    it('should track maxFloorReached across multiple floors', () => {
      useCombatStore.setState({
        currentAction: 'climb',
        climbDirection: 'up',
        currentRoomIndex: 0,
        roomsPerFloor: 1,
        currentFloor: 1,
        floorHP: getFloorMaxHP(1),
        floorMaxHP: getFloorMaxHP(1),
        activeSpell: 'manaBolt',
      });

      tickN(500);

      const combat = useCombatStore.getState();
      expect(combat.maxFloorReached).toBeGreaterThanOrEqual(combat.currentFloor);
      expect(combat.maxFloorReached).toBeGreaterThan(1);
    });

    it('should cap maxFloorReached at 100', () => {
      useCombatStore.setState({
        currentAction: 'climb',
        climbDirection: 'up',
        currentRoomIndex: 0,
        roomsPerFloor: 1,
        currentFloor: 100,
        floorHP: getFloorMaxHP(100),
        floorMaxHP: getFloorMaxHP(100),
        maxFloorReached: 100,
        activeSpell: 'manaBolt',
      });

      tickN(100);

      expect(useCombatStore.getState().currentFloor).toBe(100);
      expect(useCombatStore.getState().maxFloorReached).toBe(100);
    });

    it('should update maxFloorReached and reduce mana after climbing', () => {
      useManaStore.setState({ rawMana: 9999 });
      useCombatStore.setState({
        currentAction: 'climb',
        climbDirection: 'up',
        currentRoomIndex: 0,
        roomsPerFloor: 1,
        currentFloor: 1,
        floorHP: getFloorMaxHP(1),
        floorMaxHP: getFloorMaxHP(1),
        activeSpell: 'manaBolt',
      });

      tickN(500);

      expect(useCombatStore.getState().maxFloorReached).toBeGreaterThan(1);
      expect(useManaStore.getState().rawMana).toBeLessThan(9999);
      expect(useGameStore.getState().day).toBeGreaterThanOrEqual(1);
    });
  });

  describe('meditation mana regen flow', () => {
    it('should increase raw mana over time while meditating', () => {
      useCombatStore.setState({ currentAction: 'meditate' });
      useManaStore.setState({ rawMana: 10 });

      tickN(20);

      expect(useManaStore.getState().rawMana).toBeGreaterThan(10);
    });

    it('should track meditateTicks in mana store during meditation', () => {
      useCombatStore.setState({ currentAction: 'meditate' });

      tickN(5);

      expect(useManaStore.getState().meditateTicks).toBe(5);
    });

    it('should reset meditateTicks when action changes from meditate', () => {
      useCombatStore.setState({ currentAction: 'meditate' });
      tickN(5);
      expect(useManaStore.getState().meditateTicks).toBe(5);

      useCombatStore.setState({ currentAction: 'climb' });
      tickN(1);
      expect(useManaStore.getState().meditateTicks).toBe(0);
    });

    it('should boost mana regen with higher meditateTicks', () => {
      resetAllStores();
      useCombatStore.setState({ currentAction: 'meditate' });
      useManaStore.setState({ rawMana: 10 });
      tickN(5);
      const after5 = useManaStore.getState().rawMana;

      resetAllStores();
      useCombatStore.setState({ currentAction: 'meditate' });
      useManaStore.setState({ rawMana: 10 });
      tickN(50);
      const after50 = useManaStore.getState().rawMana;

      expect(after50 - 10).toBeGreaterThan(after5 - 10);
    });
  });

  describe('incursion strength affecting mana regen', () => {
    it('should reduce mana regen during high incursion', () => {
      resetAllStores();
      useGameStore.setState({ day: 1, hour: 0 });
      useCombatStore.setState({ currentAction: 'meditate' });
      useManaStore.setState({ rawMana: 10 });
      tickN(10);
      const lowIncursionMana = useManaStore.getState().rawMana;

      resetAllStores();
      useGameStore.setState({ day: MAX_DAY, hour: 23 });
      useCombatStore.setState({ currentAction: 'meditate' });
      useManaStore.setState({ rawMana: 10 });
      tickN(10);
      const highIncursionMana = useManaStore.getState().rawMana;

      expect(highIncursionMana).toBeLessThan(lowIncursionMana);
    });
  });
});
