// ─── Game Store (Refactored) ──────────────────────────────────────────────
// Main entry point - imports from modular store components

import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import type { GameState, GameAction, ActivityLogEntry } from './types';

import { addActivityLogEntry } from './utils/activity-log';
import {
  computeMaxMana, computeRegen, computeClickMana,
  getMeditationBonus,
} from './utils/mana-utils';
import {
  calcDamage, calcInsight, getIncursionStrength, canAffordSpellCost, deductSpellCost,
} from './utils/combat-utils';
import { generateFloorState } from './utils/room-utils';

// Re-export formatting functions for backward compatibility
export { fmt, fmtDec } from './utils/formatting';
export { getFloorMaxHP, getFloorElement } from './utils/floor-utils';

// Re-export computed stats functions for backward compatibility and tests
export {
  computeMaxMana, computeRegen, computeClickMana,
  getMeditationBonus,
} from './utils/mana-utils';
export {
  calcDamage, calcInsight, getIncursionStrength, canAffordSpellCost, deductSpellCost,
} from './utils/combat-utils';

// ─── Initial State ───────────────────────────────────────────────────────

interface MakeInitialOptions {
  loopCount?: number;
  totalInsight?: number;
  insight?: number;
  prestigeUpgrades?: Record<string, number>;
}

export function makeInitial(opts?: MakeInitialOptions): GameState {
  return {
    day: 1,
    hour: 0,
    rawMana: 100,
    maxMana: 100,
    elements: {},
    skills: {},
    skillUpgrades: {},
    skillTiers: {},
    spells: {},
    currentAction: 'meditate' as GameAction,
    currentStudyTarget: null,
    parallelStudyTarget: null,
    activeSpell: null,
    currentFloor: 100,
    floorHP: 1000,
    floorMaxHP: 1000,
    currentRoom: generateFloorState(100),
    maxFloorReached: 100,
    paused: false,
    gameOver: false,
    victory: false,
    loopCount: opts?.loopCount ?? 0,
    totalInsight: opts?.totalInsight ?? 0,
    insight: opts?.insight ?? 0,
    loopInsight: 0,
    prestigeUpgrades: opts?.prestigeUpgrades ?? {},
    signedPacts: [],
    attunements: {},
    golemancy: { enabledGolems: [] },
    memories: [],
    memorySlots: 0,
    log: [],
    activityLog: [],
    meditateTicks: 0,
    totalManaGathered: 0,
    equippedInstances: {},
    equipmentInstances: {},
    lootInventory: {},
    blueprints: {},
    spireMode: false,
  };
}

// ─── Game Store Interface ─────────────────────────────────────────────────

export interface GameStore extends GameState {
  tick: () => void;
  gatherMana: () => void;
  setAction: (action: GameAction) => void;
  addActivityLog: (eventType: string, message: string, details?: ActivityLogEntry['details']) => void;
  setSpell: (spellId: string) => void;
  cancelStudy: () => void;
  convertMana: (element: string, amount: number) => void;
  unlockElement: (element: string) => void;
  doPrestige: (id: string, selectedManaType?: string) => void;
  startNewLoop: () => void;
  togglePause: () => void;
  resetGame: () => void;
  addLog: (message: string) => void;
  addAttunementXP: (attunementId: string, amount: number) => void;
  toggleGolem: (golemId: string) => void;
  setEnabledGolems: (golemIds: string[]) => void;
  debugUnlockAttunement: (attunementId: string) => void;
  debugAddElementalMana: (element: string, amount: number) => void;
  debugSetTime: (day: number, hour: number) => void;
  debugAddAttunementXP: (attunementId: string, amount: number) => void;
  debugSetFloor: (floor: number) => void;
  resetFloorHP: () => void;
  getMaxMana: () => number;
  getRegen: () => number;
  getClickMana: () => number;
  getDamage: (spellId: string) => number;
  getMeditationMultiplier: () => number;
  canCastSpell: (spellId: string) => boolean;
  enterSpireMode: () => void;
  climbDownFloor: () => void;
  exitSpireMode: () => void;
}

// ─── Store Implementation ────────────────────────────────────────────────

export const useGameStore = create<GameStore>()(
  persist(
    (set, get) => ({
      ...makeInitial(),

      getMaxMana: () => computeMaxMana(get()),
      getRegen: () => computeRegen(get()),
      getClickMana: () => computeClickMana(get()),
      getDamage: (spellId: string) => calcDamage(get(), spellId),
      getMeditationMultiplier: () => getMeditationBonus(get().meditateTicks, {}),

      canCastSpell: (spellId: string) => {
        const state = get();
        const spell = state.spells?.[spellId];
        if (!spell) return false;
        return true;
      },

      addLog: (message: string) => {
        set((state) => ({
          log: [message, ...(state.log || []).slice(0, 49)],
        }));
      },

      addActivityLog: (eventType: string, message: string, details?: ActivityLogEntry['details']) => {
        set((state) => ({
          activityLog: addActivityLogEntry(state, eventType, message, details),
        }));
      },

      tick: () => {
        const state = get();
        if (state.gameOver || state.paused) return;

        const maxMana = computeMaxMana(state);
        const baseRegen = computeRegen(state);

        let hour = state.hour + 1;
        let day = state.day;
        if (hour >= 24) { hour -= 24; day += 1; }

        if (day > 100) {
          const insightGained = calcInsight(state);
          set({
            day, hour, gameOver: true, victory: false, loopInsight: insightGained,
            log: [`⏰ The loop ends. Gained ${insightGained} Insight.`, ...state.log.slice(0, 49)],
          });
          return;
        }

        let rawMana = state.rawMana + baseRegen;
        rawMana = Math.min(rawMana, maxMana);

        set({
          day, hour, rawMana,
          meditateTicks: state.currentAction === 'meditate' ? state.meditateTicks + 1 : 0,
        });
      },

      gatherMana: () => {
        const state = get();
        const clickMana = computeClickMana(state);
        const maxMana = computeMaxMana(state);
        set((s) => ({
          rawMana: Math.min(s.rawMana + clickMana, maxMana),
          totalManaGathered: s.totalManaGathered + clickMana,
        }));
      },

      setAction: (action: GameAction) => {
        set({ currentAction: action });
      },

      setSpell: (spellId: string) => {
        set({ activeSpell: spellId });
      },

      cancelStudy: () => {
        set({ currentStudyTarget: null, currentAction: 'meditate' });
      },

      convertMana: (element: string, amount: number) => {
        set((s) => {
          const elem = s.elements?.[element];
          if (!elem || !elem.unlocked) return s;
          const canConvert = Math.min(amount, Math.floor(s.rawMana / 10), elem.max - elem.current);
          if (canConvert > 0) {
            return {
              rawMana: s.rawMana - canConvert * 10,
              elements: { ...s.elements, [element]: { ...elem, current: elem.current + canConvert } },
            };
          }
          return s;
        });
      },

      unlockElement: (element: string) => {
        set((s) => ({
          elements: { ...s.elements, [element]: { ...s.elements[element], unlocked: true } },
        }));
      },

      doPrestige: (id: string, selectedManaType?: string) => {
        set((s) => ({
          prestigeUpgrades: { ...s.prestigeUpgrades, [id]: (s.prestigeUpgrades[id] || 0) + 1 },
        }));
      },

      startNewLoop: () => {
        const state = get();
        const insightGained = state.loopInsight || 0;
        set({
          ...makeInitial({
            loopCount: state.loopCount + 1,
            totalInsight: (state.totalInsight || 0) + insightGained,
            insight: (state.insight || 0) + insightGained,
            prestigeUpgrades: state.prestigeUpgrades,
          }),
        });
      },

      togglePause: () => {
        set((s) => ({ paused: !s.paused }));
      },

      resetGame: () => {
        set(makeInitial());
      },

      addAttunementXP: (attunementId: string, amount: number) => {
        set((s) => {
          const attState = s.attunements?.[attunementId];
          if (!attState) return s;
          return {
            attunements: { ...s.attunements, [attunementId]: { ...attState, experience: attState.experience + amount } },
          };
        });
      },

      toggleGolem: (golemId: string) => {
        set((s) => {
          const enabledGolems = s.golemancy?.enabledGolems || [];
          const isEnabled = enabledGolems.includes(golemId);
          return {
            golemancy: { ...s.golemancy, enabledGolems: isEnabled ? enabledGolems.filter(id => id !== golemId) : [...enabledGolems, golemId] },
          };
        });
      },

      setEnabledGolems: (golemIds: string[]) => {
        set((s) => ({
          golemancy: { ...s.golemancy, enabledGolems: golemIds },
        }));
      },

      debugUnlockAttunement: (attunementId: string) => {
        set((s) => ({
          attunements: { ...s.attunements, [attunementId]: { id: attunementId, active: true, level: 1, experience: 0 } },
        }));
      },

      debugAddElementalMana: (element: string, amount: number) => {
        set((s) => {
          const elem = s.elements?.[element];
          if (!elem) return s;
          return {
            elements: { ...s.elements, [element]: { ...elem, current: Math.min(elem.current + amount, elem.max) } },
          };
        });
      },

      debugSetTime: (day: number, hour: number) => {
        set({ day, hour });
      },

      debugAddAttunementXP: (attunementId: string, amount: number) => {
        get().addAttunementXP(attunementId, amount);
      },

      debugSetFloor: (floor: number) => {
        set((s) => ({
          currentFloor: floor,
          currentRoom: generateFloorState(floor),
          floorMaxHP: 100 + floor * 50,
          floorHP: 100 + floor * 50,
        }));
      },

      resetFloorHP: () => {
        set((s) => ({
          floorHP: s.floorMaxHP,
          currentRoom: generateFloorState(s.currentFloor),
        }));
      },

      enterSpireMode: () => {
        set({ spireMode: true });
      },

      climbDownFloor: () => {
        set((s) => {
          if (s.currentFloor <= 1) return s;
          const newFloor = s.currentFloor - 1;
          return {
            currentFloor: newFloor,
            currentRoom: generateFloorState(newFloor),
            floorMaxHP: 100 + newFloor * 50,
            floorHP: 100 + newFloor * 50,
          };
        });
      },

      exitSpireMode: () => {
        set({ spireMode: false });
      },
    }),
    {
      name: 'mana-loop-game-store',
    }
  )
);

// ─── Game Loop Hook ───────────────────────────────────────────────────────────

export function useGameLoop() {
  const tick = useGameStore((s) => s.tick);
  return {
    start: () => {
      const interval = setInterval(tick, 1000);
      return () => clearInterval(interval);
    },
  };
}
