import { describe, it, expect, beforeEach } from 'vitest';
import { useGameStore } from '../stores/gameStore';
import { useManaStore, makeInitialElements } 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 { useCraftingStore } from '../stores/craftingStore';
import { useAttunementStore } from '../stores/attunementStore';
import { HOURS_PER_TICK, MAX_DAY } from '../constants';
import { getFloorMaxHP } from '../utils';
import { fmt, formatHour } from '../utils/formatting';

// ─── Full Store Reset ─────────────────────────────────────────────────────────

function resetAllStores() {
  useUIStore.setState({
    paused: false,
    gameOver: false,
    victory: false,
    logs: [],
  });

  useGameStore.setState({
    day: 1,
    hour: 0,
    incursionStrength: 0,
    containmentWards: 0,
    initialized: true,
  });

  useManaStore.setState({
    rawMana: 100,
    meditateTicks: 0,
    totalManaGathered: 0,
    elements: makeInitialElements(50, {}),
  });

  useCombatStore.setState({
    currentFloor: 1,
    floorHP: getFloorMaxHP(1),
    floorMaxHP: getFloorMaxHP(1),
    maxFloorReached: 1,
    activeSpell: 'manaBolt',
    currentAction: 'meditate',
    castProgress: 0,
    spireMode: false,
    currentRoom: { roomType: 'combat', enemies: [] },
    clearedFloors: {},
    climbDirection: null,
    isDescending: false,
    golemancy: { activeGolems: [], lastSummonFloor: 0, golemDesigns: {}, golemLoadout: [] },
    equipmentSpellStates: [],
    comboHitCount: 0,
    floorHitCount: 0,
    spells: { manaBolt: { learned: true, level: 1, studyProgress: 0 } },
    activityLog: [],
    achievements: { unlocked: [], progress: {} },
    totalSpellsCast: 0,
    totalDamageDealt: 0,
    totalCraftsCompleted: 0,
  });

  usePrestigeStore.setState({
    loopCount: 0,
    insight: 0,
    totalInsight: 0,
    loopInsight: 0,
    prestigeUpgrades: {},
    pactSlots: 1,
    defeatedGuardians: [],
    signedPacts: [],
    signedPactDetails: {},
    pactRitualFloor: null,
    pactRitualProgress: 0,
  });

  useDisciplineStore.setState({
    disciplines: {},
    activeIds: [],
    concurrentLimit: 1,
    totalXP: 0,
  });

  useCraftingStore.setState({
    designs: {},
    designProgress: 0,
    designSlot2Active: false,
    designProgress2: 0,
    preparationProgress: 0,
    applicationProgress: 0,
    equipmentCraftingProgress: 0,
    equipmentInstances: {},
    equippedInstances: {},
    lootInventory: { materials: {}, equipment: [], blueprints: [] },
    unlockedEffects: [],
    unlockedRecipes: [],
    enchantmentPowerBonus: 0,
  });

  useAttunementStore.setState({
    attunements: {
      enchanter: { active: true, level: 1, xp: 0 },
    },
  });
}

// ═══════════════════════════════════════════════════════════════════════════════
// DAY 30 BLANK PAGE BUG REPRODUCTION
// ═══════════════════════════════════════════════════════════════════════════════

describe('Day 30 Blank Page Bug', () => {
  beforeEach(resetAllStores);

  it('should not crash when setting day to 30 and running ticks to game over', () => {
    // Reproduce: Debug panel sets day to 20, then day to 30
    useGameStore.setState({ day: 20, hour: 0 });
    useGameStore.setState({ day: 30, hour: 0 });

    // Verify state is correct
    expect(useGameStore.getState().day).toBe(30);
    expect(useGameStore.getState().hour).toBe(0);
    expect(useUIStore.getState().gameOver).toBe(false);

    // Run ticks until game over (day > 30)
    let ticks = 0;
    const maxTicks = 1000;
    while (!useUIStore.getState().gameOver && ticks < maxTicks) {
      useGameStore.getState().tick();
      ticks++;
    }

    // Game over should have triggered
    expect(useUIStore.getState().gameOver).toBe(true);
    expect(useUIStore.getState().victory).toBe(false);

    // loopInsight should be a valid number (not undefined/NaN)
    const loopInsight = usePrestigeStore.getState().loopInsight;
    expect(typeof loopInsight).toBe('number');
    expect(Number.isFinite(loopInsight)).toBe(true);

    // day and hour should be valid
    const day = useGameStore.getState().day;
    const hour = useGameStore.getState().hour;
    expect(typeof day).toBe('number');
    expect(typeof hour).toBe('number');
    expect(Number.isFinite(day)).toBe(true);
    expect(Number.isFinite(hour)).toBe(true);

    console.log(`Game over after ${ticks} ticks. Day=${day}, Hour=${hour}, LoopInsight=${loopInsight}`);
  });

  it('should produce valid GameOverScreen props after loop ends at day 30', () => {
    // Set day to 30 directly (simulating debug panel)
    useGameStore.setState({ day: 30, hour: 0 });

    // Run ticks until game over
    let ticks = 0;
    const maxTicks = 1000;
    while (!useUIStore.getState().gameOver && ticks < maxTicks) {
      useGameStore.getState().tick();
      ticks++;
    }

    expect(useUIStore.getState().gameOver).toBe(true);

    // These are the exact props passed to GameOverScreen in page.tsx
    const day = useGameStore.getState().day;
    const hour = useGameStore.getState().hour;
    const loopInsight = usePrestigeStore.getState().loopInsight;
    const insight = usePrestigeStore.getState().insight;

    // All must be finite numbers for fmt() and formatHour() to work
    expect(Number.isFinite(day)).toBe(true);
    expect(Number.isFinite(hour)).toBe(true);
    expect(Number.isFinite(loopInsight)).toBe(true);
    expect(Number.isFinite(insight)).toBe(true);

    // fmt() should not throw
    expect(() => fmt(loopInsight)).not.toThrow();
    expect(() => fmt(insight)).not.toThrow();

    // formatHour() should not throw
    expect(() => formatHour(hour)).not.toThrow();
  });

  it('should handle game over when jumping from day 20 to day 30 with incursion', () => {
    // Set up a more realistic state with some progress
    useManaStore.setState({ rawMana: 500, totalManaGathered: 10000 });
    useCombatStore.setState({ maxFloorReached: 50 });

    // Jump to day 20, then day 30
    useGameStore.setState({ day: 20, hour: 0 });
    useGameStore.setState({ day: 30, hour: 0 });

    // Run ticks until game over
    let ticks = 0;
    const maxTicks = 1000;
    while (!useUIStore.getState().gameOver && ticks < maxTicks) {
      useGameStore.getState().tick();
      ticks++;
    }

    expect(useUIStore.getState().gameOver).toBe(true);
    expect(usePrestigeStore.getState().loopInsight).toBeGreaterThan(0);
  });
});
