import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import { createSafeStorage } from '../utils/safe-persist';
import type { GameAction, SpellState, FloorState, GolemancyState, ActivityLogEntry, AchievementState, EquipmentSpellState, ActivityEventType, RuntimeActiveGolem, EnemyState, EquipmentInstance } from '../types';
import { getFloorMaxHP } from '../utils';
import { generateSpireFloorState, getRoomsForFloor } from '../utils/spire-utils';
import { addActivityLogEntry } from '../utils/activity-log';
import { processCombatTick, makeInitialSpells } from './combat-actions';
import { getGuardianForFloor } from '../data/guardian-encounters';
import type { CombatStore } from './combat-state.types';
import { enterDescentMode, advanceRoomOrFloor, onEnterRoomDescend, createEnterSpireMode } from './combat-descent-actions';
import { createDefaultCombatState } from './combat-reset';
import { onEnterLibraryRoom, tickNonCombatRoom, skipNonCombatRoom, stayLongerInRoom } from './non-combat-room-actions';
import { useDisciplineStore } from './discipline-slice';
import { addGolemDesign, removeGolemDesign, toggleGolemLoadoutEntry } from './golemancy-actions';
import { createChannelActions } from './combat-channel-actions';

export const useCombatStore = create<CombatStore>()(
  persist(
    (set, get) => ({
      currentFloor: 1,
      floorHP: getFloorMaxHP(1),
      floorMaxHP: getFloorMaxHP(1),
      maxFloorReached: 0,
      activeSpell: 'manaBolt',
      currentAction: 'meditate',
      castProgress: 0,
      spireMode: false,

      // Room system
      currentRoom: generateSpireFloorState(1, 0, getRoomsForFloor(1, 1 * 12345)),

      // Spire climbing state
      clearedFloors: {},
      climbDirection: null,
      isDescending: false,

      // ─── Spec: Room navigation state ──────────────────────────────────────
      startFloor: 1,
      exitFloor: 1,
      currentRoomIndex: 0,
      roomsPerFloor: 1,

      // ─── Spec: Run identity (climbing spec §4.2, §7) ────────────────────
      runId: 0,

      // ─── Spec: Descent tracking state ─────────────────────────────────────
      descentPeak: null,
      roomResetState: {},
      clearedRooms: {},
      isDescentComplete: false,

      // Golemancy (component-based)
      golemancy: {
        golemDesigns: {},
        golemLoadout: [],
        activeGolems: [] as RuntimeActiveGolem[],
        lastSummonFloor: 0,
      },

      // Equipment spell states
      equipmentSpellStates: [],

      // Per-weapon cast progress records (spec §3.1, D-01 fix)
      weaponCastProgress: {},

      // Combat tracking
      comboHitCount: 0,
      floorHitCount: 0,

      // Melee sword progress accumulators (spec §3.1)
      meleeSwordProgress: {},

      // Guardian defensive state
      guardianShield: 0,
      guardianShieldMax: 0,
      guardianBarrier: 0,
      guardianBarrierMax: 0,

      // Spells
      spells: {
        manaBolt: { learned: true, level: 1, studyProgress: 0 },
      },

      // Activity Log
      activityLog: [],

      // Achievements
      achievements: {
        unlocked: [],
        progress: {},
      },

      // Stats tracking
      totalSpellsCast: 0,
      totalDamageDealt: 0,
      totalCraftsCompleted: 0,

      // Invocation system
      invocationCharge: 0,
      activeInvocation: null,

      // Room Enchantments state
      lastRoomCoverage: 0,

      // Transference Channel state
      isChanneling: false,
      channelSpeedMultiplier: 1.5,
      channelDrainRate: 0.08,

      setCurrentFloor: (floor: number) => {
        set({
          currentFloor: floor,
          floorHP: getFloorMaxHP(floor),
          floorMaxHP: getFloorMaxHP(floor),
        });
      },

      advanceFloor: () => {
        set((state) => {
          const newFloor = Math.min(state.currentFloor + 1, 100);
          return {
            currentFloor: newFloor,
            floorHP: getFloorMaxHP(newFloor),
            floorMaxHP: getFloorMaxHP(newFloor),
            maxFloorReached: Math.max(state.maxFloorReached, newFloor),
            castProgress: 0,
          };
        });
      },

      setFloorHP: (hp: number) => {
        set({ floorHP: Math.max(0, hp) });
      },

      setMaxFloorReached: (floor: number) => {
        set((state) => ({
          maxFloorReached: Math.max(state.maxFloorReached, floor),
        }));
      },

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

      setSpell: (spellId: string) => {
        const state = get();
        if (state.spells[spellId]?.learned) {
          set({ activeSpell: spellId });
        }
      },

      setCastProgress: (progress: number) => {
        set({ castProgress: progress });
      },

      // Room state
      setCurrentRoom: (room: FloorState) => {
        set({ currentRoom: room });
      },

      // Spire climbing
      setClimbDirection: (direction: 'up' | 'down' | null) => {
        set({ climbDirection: direction });
      },

      setClearedFloor: (floor: number, cleared: boolean) => {
        set((state) => ({
          clearedFloors: { ...state.clearedFloors, [floor]: cleared },
        }));
      },

      setIsDescending: (descending: boolean) => {
        set({ isDescending: descending });
      },

      climbDownFloor: () => {
        set((s) => {
          if (s.currentFloor <= 1) return s;
          const newFloor = s.currentFloor - 1;
          const seed = newFloor * 12345 + s.runId;
          const rooms = getRoomsForFloor(newFloor, seed);
          const newRoom = generateSpireFloorState(newFloor, 0, rooms, s.runId);
          return {
            currentFloor: newFloor,
            currentRoom: newRoom,
            floorMaxHP: getFloorMaxHP(newFloor),
            floorHP: getFloorMaxHP(newFloor),
            castProgress: 0,
            weaponCastProgress: {},
          };
        });
      },

      exitSpireMode: () => {
        const s = get();
        const seed = s.exitFloor * 12345 + s.runId;
        const rooms = getRoomsForFloor(s.exitFloor, seed);
        set({
          spireMode: false,
          currentAction: 'meditate',
          climbDirection: null,
          isDescending: false,
          currentFloor: s.exitFloor,
          floorHP: getFloorMaxHP(s.exitFloor),
          floorMaxHP: getFloorMaxHP(s.exitFloor),
          currentRoom: generateSpireFloorState(s.exitFloor, 0, rooms, s.runId),
          castProgress: 0,
          clearedFloors: {},
          clearedRooms: {},
          roomResetState: {},
          descentPeak: null,
          isDescentComplete: false,
          currentRoomIndex: 0,
          roomsPerFloor: 1,
          maxFloorReached: Math.max(s.maxFloorReached, 1),
          golemancy: { ...s.golemancy, activeGolems: [] as RuntimeActiveGolem[] },
          invocationCharge: 0,
          activeInvocation: null,
          isChanneling: false,
          lastRoomCoverage: 0,
        });
        // Deactivate all disciplines on spire exit for safety
        useDisciplineStore.getState().deactivateAll();
        get().addActivityLog('floor_transition', 'Exited the Spire');
      },

      startClimbUp: () => set({ climbDirection: 'up', currentAction: 'climb' }),
      startClimbDown: () => set({ climbDirection: 'down', currentAction: 'climb' }),
      startPracticing: () => set((s) => s.currentAction !== 'meditate' ? s : { currentAction: 'practicing' }),
      stopPracticing: () => set((s) => s.currentAction !== 'practicing' ? s : { currentAction: 'meditate' }),

      // ─── Spec: Descent actions (delegated to combat-descent-actions.ts) ────
      enterDescentMode: () => enterDescentMode(get, set),
      advanceRoomOrFloor: () => advanceRoomOrFloor(get, set),
      onEnterRoomDescend: () => onEnterRoomDescend(get, set),
      onEnterLibraryRoom: () => onEnterLibraryRoom(get, set),
      tickNonCombatRoom: (hours: number) => tickNonCombatRoom(get, set, hours, advanceRoomOrFloor),
      skipNonCombatRoom: () => skipNonCombatRoom(get, set, advanceRoomOrFloor),
      stayLongerInRoom: () => stayLongerInRoom(get, set),

      // Golemancy
      addGolemDesign: (d) => addGolemDesign(set, d),
      removeGolemDesign: (id) => removeGolemDesign(set, id),
      toggleGolemLoadoutEntry: (id) => toggleGolemLoadoutEntry(set, id),

      enterSpireMode: createEnterSpireMode(get, set),

      learnSpell: (spellId: string) => {
        set((state) => ({
          spells: {
            ...state.spells,
            [spellId]: { learned: true, level: 1, studyProgress: 0 },
          },
        }));
      },

      setSpellState: (spellId: string, spellState: Partial<SpellState>) => {
        set((state) => ({
          spells: {
            ...state.spells,
            [spellId]: { ...(state.spells[spellId] || { learned: false, level: 0, studyProgress: 0 }), ...spellState },
          },
        }));
      },

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

      // Stats
      incrementSpellsCast: () => {
        set((state) => ({ totalSpellsCast: state.totalSpellsCast + 1 }));
      },

      addDamageDealt: (damage: number) => {
        set((state) => ({ totalDamageDealt: state.totalDamageDealt + damage }));
      },

      incrementCraftsCompleted: () => {
        set((state) => ({ totalCraftsCompleted: state.totalCraftsCompleted + 1 }));
      },

      resetGuardianDefensiveState: () => {
        set({ guardianShield: 0, guardianShieldMax: 0, guardianBarrier: 0, guardianBarrierMax: 0 });
      },

      resetInvocationState: () => {
        set({ invocationCharge: 0, activeInvocation: null });
      },

      setLastRoomCoverage: (value: number) => {
        set({ lastRoomCoverage: Math.max(0, Math.min(100, value)) });
      },

      ...createChannelActions(get, set),

      initGuardianDefensiveState: () => {
        const state = get();
        const guardian = getGuardianForFloor(state.currentFloor);
        if (!guardian) return;
        set({
          guardianShield: guardian.shield ?? 0,
          guardianShieldMax: guardian.shield ?? 0,
          guardianBarrier: guardian.barrier ?? 0,
          guardianBarrierMax: guardian.barrier ?? 0,
        });
      },

      processCombatTick: (
        rawMana: number,
        elements: Record<string, { current: number; max: number; unlocked: boolean }>,
        maxMana: number,
        attackSpeedMult: number,
        onFloorCleared: (floor: number, wasGuardian: boolean) => void,
        onDamageDealt: (damage: number, skipSpecials?: boolean) => { rawMana: number; elements: Record<string, { current: number; max: number; unlocked: boolean }> },
        signedPacts: number[],
        golemancyState: { activeGolems: RuntimeActiveGolem[] },
        golemApplyDamageToRoom: (dmg: number) => { floorHP: number; floorMaxHP: number; roomCleared: boolean },
        applyEnemyDefenses: (
          dmg: number,
          enemy: EnemyState | null,
          roomType: string,
          addLog: (msg: string) => void,
          bypassArmor?: boolean,
          bypassBarrier?: boolean,
        ) => number,
        equippedSwords?: Record<string, EquipmentInstance>,
      ) => {
        return processCombatTick(
          get,
          set,
          rawMana,
          elements,
          maxMana,
          attackSpeedMult,
          onFloorCleared,
          onDamageDealt,
          signedPacts,
          golemancyState,
          golemApplyDamageToRoom,
          applyEnemyDefenses,
          equippedSwords,
        );
      },

      resetCombat: (startFloor: number, spellsToKeep: string[] = []) => {
        set(createDefaultCombatState(startFloor, spellsToKeep));
      },

    }),
    {
      storage: createSafeStorage(),
      name: 'mana-loop-combat',
      version: 1,
      partialize: (state) => ({
        currentFloor: state.currentFloor,
        maxFloorReached: state.maxFloorReached,
        spells: state.spells,
        activeSpell: state.activeSpell,
        currentAction: state.currentAction,
        floorHP: state.floorHP,
        floorMaxHP: state.floorMaxHP,
        castProgress: state.castProgress,
        spireMode: state.spireMode,
        currentRoom: state.currentRoom,
        clearedFloors: state.clearedFloors,
        golemancy: state.golemancy,
        equipmentSpellStates: state.equipmentSpellStates,
        weaponCastProgress: state.weaponCastProgress,
        comboHitCount: state.comboHitCount,
        floorHitCount: state.floorHitCount,
        activityLog: state.activityLog,
        achievements: state.achievements,
        totalSpellsCast: state.totalSpellsCast,
        totalDamageDealt: state.totalDamageDealt,
        totalCraftsCompleted: state.totalCraftsCompleted,
        guardianShield: state.guardianShield,
        guardianShieldMax: state.guardianShieldMax,
        guardianBarrier: state.guardianBarrier,
        guardianBarrierMax: state.guardianBarrierMax,
        meleeSwordProgress: state.meleeSwordProgress,
        runId: state.runId,
        invocationCharge: state.invocationCharge,
        activeInvocation: state.activeInvocation,
        isChanneling: state.isChanneling,
        channelSpeedMultiplier: state.channelSpeedMultiplier,
        channelDrainRate: state.channelDrainRate,
        lastRoomCoverage: state.lastRoomCoverage,
      }),
    }
  )
);

export { makeInitialSpells } from './combat-actions';
