import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { useGameStore } from '../stores/gameStore';
import { useManaStore } from '../stores/manaStore';
import { useCombatStore } from '../stores/combatStore';
import { usePrestigeStore } from '../stores/prestigeStore';
import { useCraftingStore } from '../stores/craftingStore';
import { useAttunementStore } from '../stores/attunementStore';
import { useDisciplineStore } from '../stores/discipline-slice';
import { useUIStore } from '../stores/uiStore';

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

const ALL_STORE_KEYS = [
  'mana-loop-game-storage',
  'mana-loop-mana',
  'mana-loop-combat',
  'mana-loop-prestige',
  'mana-loop-crafting',
  'mana-loop-attunements',
  'mana-loop-discipline-store',
  'mana-loop-ui-storage',
] as const;

function clearAllPersistedState() {
  for (const key of ALL_STORE_KEYS) {
    localStorage.removeItem(key);
  }
}

function setKnownStoreStates() {
  useGameStore.setState({ day: 5, hour: 12 });
  useManaStore.setState({ rawMana: 42, totalManaGathered: 100 });
  useCombatStore.setState({ currentFloor: 7, maxFloorReached: 7 });
  usePrestigeStore.setState({ insight: 50, totalInsight: 50, loopCount: 2 });
  useAttunementStore.setState({
    attunements: { enchanter: { id: 'enchanter', active: true, level: 3, experience: 50 } },
  });
  useDisciplineStore.setState({ totalXP: 200, concurrentLimit: 2 });
  useUIStore.setState({ paused: false, gameOver: false });
  // Crafting store: change something to trigger persist
  useCraftingStore.setState((s) => ({ lootInventory: { ...s.lootInventory, materials: { ironOre: 5 } } }));
}

// ═══════════════════════════════════════════════════════════════════════════════
// PERSISTENCE TESTS
// ═══════════════════════════════════════════════════════════════════════════════

describe('Persistence', () => {
  beforeEach(() => {
    clearAllPersistedState();
  });

  afterEach(() => {
    clearAllPersistedState();
  });

  describe('localStorage keys exist after state changes', () => {
    it('should persist game store state to localStorage', () => {
      useGameStore.setState({ day: 5, hour: 12 });
      const raw = localStorage.getItem('mana-loop-game-storage');
      expect(raw).not.toBeNull();
      const parsed = JSON.parse(raw!);
      expect(parsed.state.day).toBe(5);
      expect(parsed.state.hour).toBe(12);
    });

    it('should persist mana store state to localStorage', () => {
      useManaStore.setState({ rawMana: 42, totalManaGathered: 100 });
      const raw = localStorage.getItem('mana-loop-mana');
      expect(raw).not.toBeNull();
      const parsed = JSON.parse(raw!);
      expect(parsed.state.rawMana).toBe(42);
      expect(parsed.state.totalManaGathered).toBe(100);
    });

    it('should persist combat store state to localStorage', () => {
      useCombatStore.setState({ currentFloor: 7, maxFloorReached: 7 });
      const raw = localStorage.getItem('mana-loop-combat');
      expect(raw).not.toBeNull();
      const parsed = JSON.parse(raw!);
      expect(parsed.state.currentFloor).toBe(7);
      expect(parsed.state.maxFloorReached).toBe(7);
    });

    it('should persist prestige store state to localStorage', () => {
      usePrestigeStore.setState({ insight: 50, totalInsight: 50, loopCount: 2 });
      const raw = localStorage.getItem('mana-loop-prestige');
      expect(raw).not.toBeNull();
      const parsed = JSON.parse(raw!);
      expect(parsed.state.insight).toBe(50);
      expect(parsed.state.totalInsight).toBe(50);
      expect(parsed.state.loopCount).toBe(2);
    });

    it('should persist attunement store state to localStorage', () => {
      useAttunementStore.setState({
        attunements: { enchanter: { id: 'enchanter', active: true, level: 3, experience: 50 } },
      });
      const raw = localStorage.getItem('mana-loop-attunements');
      expect(raw).not.toBeNull();
      const parsed = JSON.parse(raw!);
      expect(parsed.state.attunements.enchanter.level).toBe(3);
      expect(parsed.state.attunements.enchanter.experience).toBe(50);
    });

    it('should persist discipline store state to localStorage', () => {
      useDisciplineStore.setState({ totalXP: 200, concurrentLimit: 2 });
      const raw = localStorage.getItem('mana-loop-discipline-store');
      expect(raw).not.toBeNull();
      const parsed = JSON.parse(raw!);
      expect(parsed.state.totalXP).toBe(200);
      expect(parsed.state.concurrentLimit).toBe(2);
    });

    it('should persist UI store state to localStorage', () => {
      useUIStore.setState({ paused: true, gameOver: true });
      const raw = localStorage.getItem('mana-loop-ui-storage');
      expect(raw).not.toBeNull();
      const parsed = JSON.parse(raw!);
      expect(parsed.state.paused).toBe(true);
      expect(parsed.state.gameOver).toBe(true);
    });

    it('should persist crafting store state to localStorage', () => {
      useCraftingStore.setState((s) => ({
        lootInventory: { ...s.lootInventory, materials: { ironOre: 5 } },
      }));
      const raw = localStorage.getItem('mana-loop-crafting');
      expect(raw).not.toBeNull();
      const parsed = JSON.parse(raw!);
      expect(parsed.state.lootInventory.materials.ironOre).toBe(5);
    });
  });

  describe('all localStorage keys are writable', () => {
    it('should write all 8 store keys when state changes', () => {
      setKnownStoreStates();

      for (const key of ALL_STORE_KEYS) {
        const raw = localStorage.getItem(key);
        expect(raw).not.toBeNull(`Expected localStorage key "${key}" to exist after state changes`);
        const parsed = JSON.parse(raw!);
        expect(parsed).toHaveProperty('state');
        expect(parsed).toHaveProperty('version');
      }
    });
  });

  describe('resetGame clears localStorage with correct keys', () => {
    it('should not use wrong localStorage keys (mismatch bug)', () => {
      setKnownStoreStates();

      // The old resetGame used wrong keys like 'mana-loop-mana-storage' instead of 'mana-loop-mana'
      // After reset, correct keys should be restored to defaults, not stale
      useGameStore.getState().resetGame();

      // Verify wrong keys are never written
      const wrongKeys = [
        'mana-loop-mana-storage',
        'mana-loop-combat-storage',
        'mana-loop-prestige-storage',
        'mana-loop-crafting-storage',
        'mana-loop-attunement-storage',
        'mana-loop-game',  // missing -storage suffix (only game uses it)
      ];
      for (const wrongKey of wrongKeys) {
        expect(localStorage.getItem(wrongKey)).toBeNull(
          `Wrong key "${wrongKey}" should never exist`
        );
      }
    });

    it('should reset all stores to initial values', () => {
      setKnownStoreStates();
      useGameStore.getState().resetGame();

      // Game store should be reset
      expect(useGameStore.getState().day).toBe(1);
      expect(useGameStore.getState().hour).toBe(0);

      // Mana store should be reset
      // Note: resetMana uses 10 + prestigeUpgrades.quickStart, with no upgrades = 10
      expect(useManaStore.getState().rawMana).toBeGreaterThanOrEqual(0);

      // Combat store should be reset
      expect(useCombatStore.getState().currentFloor).toBe(1);

      // Prestige store should be reset
      expect(usePrestigeStore.getState().insight).toBe(0);
      expect(usePrestigeStore.getState().totalInsight).toBe(0);
    });
  });

  describe('safeStorage getItem/setItem round-trip', () => {
    it('should write and read back data correctly', () => {
      const testData = { state: { day: 5, hour: 12 }, version: 1 };
      localStorage.setItem('mana-loop-game-storage', JSON.stringify(testData));
      const raw = localStorage.getItem('mana-loop-game-storage');
      expect(raw).not.toBeNull();
      const parsed = JSON.parse(raw!);
      expect(parsed.state.day).toBe(5);
      expect(parsed.state.hour).toBe(12);
      expect(parsed.version).toBe(1);
    });
  });
});
