import { describe, it, expect, beforeEach } from 'vitest';
import { useGameStore } from '../stores/gameStore';
import { useManaStore } from '../stores/manaStore';
import { useCombatStore } from '../stores/combatStore';
import { usePrestigeStore } from '../stores/prestigeStore';
import { useUIStore } from '../stores/uiStore';
import { useDisciplineStore } from '../stores/discipline-slice';
import { resetAllStores, tickN } from './cross-module-helpers';

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

  describe('prestige loop reset', () => {
    it('should reset game day/hour on startNewLoop', () => {
      useGameStore.setState({ day: 30, hour: 12, incursionStrength: 0.5 });
      usePrestigeStore.setState({ loopInsight: 100, insight: 50 });

      useGameStore.getState().startNewLoop();

      expect(useGameStore.getState().day).toBe(1);
      expect(useGameStore.getState().hour).toBe(0);
      expect(useGameStore.getState().incursionStrength).toBe(0);
    });

    it('should preserve insight across loop reset', () => {
      usePrestigeStore.setState({ insight: 200, loopInsight: 50 });

      useGameStore.getState().startNewLoop();

      expect(usePrestigeStore.getState().insight).toBeGreaterThanOrEqual(250);
    });

    it('should increment loop count on startNewLoop', () => {
      usePrestigeStore.setState({ loopCount: 2, insight: 500 });

      useGameStore.getState().startNewLoop();

      expect(usePrestigeStore.getState().loopCount).toBe(3);
    });

    it('should clear defeatedGuardians and signedPacts on new loop', () => {
      usePrestigeStore.setState({
        defeatedGuardians: [10, 20, 30],
        signedPacts: [10],
        insight: 1000,
      });

      useGameStore.getState().startNewLoop();

      expect(usePrestigeStore.getState().defeatedGuardians).toEqual([]);
      expect(usePrestigeStore.getState().signedPacts).toEqual([]);
    });

    it('should clear pact ritual state on new loop', () => {
      usePrestigeStore.setState({
        pactRitualFloor: 50,
        pactRitualProgress: 10,
        insight: 1000,
      });

      useGameStore.getState().startNewLoop();

      expect(usePrestigeStore.getState().pactRitualFloor).toBeNull();
      expect(usePrestigeStore.getState().pactRitualProgress).toBe(0);
    });

    it('should reset combat floor on new loop', () => {
      usePrestigeStore.setState({ insight: 1000 });
      useCombatStore.setState({ currentFloor: 50, maxFloorReached: 50 });

      useGameStore.getState().startNewLoop();

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

    it('should clear gameOver and victory flags on new loop', () => {
      useUIStore.setState({ gameOver: true, victory: false });
      usePrestigeStore.setState({ insight: 1000 });

      useGameStore.getState().startNewLoop();

      expect(useUIStore.getState().gameOver).toBe(false);
      expect(useUIStore.getState().victory).toBe(false);
    });

    it('should reset mana on new loop', () => {
      usePrestigeStore.setState({ insight: 1000 });
      useManaStore.setState({
        rawMana: 5,
        totalManaGathered: 9999,
      });

      useGameStore.getState().startNewLoop();

      expect(useManaStore.getState().rawMana).toBeGreaterThan(5);
      expect(useManaStore.getState().totalManaGathered).toBe(0);
    });

    it('should preserve prestige upgrades across loop reset', () => {
      usePrestigeStore.setState({
        insight: 1000,
        prestigeUpgrades: { manaWell: 3, spireKey: 1 },
      });

      useGameStore.getState().startNewLoop();

      expect(usePrestigeStore.getState().prestigeUpgrades.manaWell).toBe(3);
      expect(usePrestigeStore.getState().prestigeUpgrades.spireKey).toBe(1);
    });
  });

  describe('discipline mana drain and XP via tick', () => {
    it('should accrue discipline XP when enough mana', () => {
      useDisciplineStore.getState().activate('raw-mastery');
      useManaStore.setState({ rawMana: 99999 });

      tickN(10);

      expect(useDisciplineStore.getState().totalXP).toBeGreaterThan(0);
    });

    it('should drain raw mana for raw-type disciplines', () => {
      useDisciplineStore.getState().activate('raw-mastery');
      useManaStore.setState({ rawMana: 99999 });
      const rawManaBefore = useManaStore.getState().rawMana;

      // Call processTick directly (not game tick) to isolate discipline drain
      const result = useDisciplineStore.getState().processTick({ rawMana: rawManaBefore, elements: {} });

      expect(useDisciplineStore.getState().totalXP).toBeGreaterThan(0);
      const disc = useDisciplineStore.getState().disciplines['raw-mastery'];
      expect(disc).toBeDefined();
      expect(disc!.xp).toBeGreaterThan(0);
      // raw-mastery: drainBase=1, xp=0 → drain=1; rawMana should be reduced by 1
      expect(result.rawMana).toBe(rawManaBefore - 1);
    });

    it('should auto-pause discipline when insufficient mana and not accrue XP', () => {
      useDisciplineStore.getState().activate('raw-mastery');
      useManaStore.setState({ rawMana: 0 });

      tickN(5);

      const disc = useDisciplineStore.getState().disciplines['raw-mastery'];
      expect(disc).toBeDefined();
      expect(disc!.autoPaused).toBe(true);
      // XP should NOT accrue while auto-paused due to insufficient mana
      expect(useDisciplineStore.getState().totalXP).toBe(0);
    });

    it('should respect concurrent limit', () => {
      useDisciplineStore.getState().activate('raw-mastery');
      useManaStore.setState({ rawMana: 99999 });

      tickN(10);

      expect(useDisciplineStore.getState().totalXP).toBeGreaterThan(0);
      const activeIds = useDisciplineStore.getState().activeIds;
      expect(activeIds.length).toBeLessThanOrEqual(
        useDisciplineStore.getState().concurrentLimit,
      );
    });
  });

  describe('pact ritual completion via tick', () => {
    it('should complete pact ritual after enough ticks', () => {
      usePrestigeStore.setState({
        defeatedGuardians: [10],
        pactRitualFloor: 10,
        pactRitualProgress: 0,
        signedPacts: [],
        pactSlots: 2,
      });

      tickN(500);

      expect(usePrestigeStore.getState().signedPacts).toContain(10);
      expect(usePrestigeStore.getState().pactRitualFloor).toBeNull();
      expect(usePrestigeStore.getState().pactRitualProgress).toBe(0);
    });

    it('should not advance pact ritual when not active', () => {
      usePrestigeStore.setState({ pactRitualFloor: null });

      tickN(50);

      expect(usePrestigeStore.getState().pactRitualProgress).toBe(0);
    });
  });
});
