'use client';

import { createContext, useContext, useMemo, type ReactNode } from 'react';
import { useSkillStore } from '@/lib/game/stores/skillStore';
import { useManaStore } from '@/lib/game/stores/manaStore';
import { usePrestigeStore } from '@/lib/game/stores/prestigeStore';
import { useUIStore } from '@/lib/game/stores/uiStore';
import { useCombatStore } from '@/lib/game/stores/combatStore';
import { useGameStore, useGameLoop } from '@/lib/game/stores/gameStore';
import { computeEffects, hasSpecial, SPECIAL_EFFECTS } from '@/lib/game/upgrade-effects';
import { getStudySpeedMultiplier, getStudyCostMultiplier } from '@/lib/game/constants';
import {
  computeMaxMana,
  computeRegen,
  computeClickMana,
  getMeditationBonus,
  canAffordSpellCost,
  calcDamage,
  getFloorElement,
  getBoonBonuses,
  getIncursionStrength,
} from '@/lib/game/utils';
import {
  ELEMENTS,
  GUARDIANS,
  SPELLS_DEF,
  HOURS_PER_TICK,
  TICK_MS,
} from '@/lib/game/constants';
import type { ElementDef, GuardianDef, SpellDef, GameAction } from '@/lib/game/types';

// Define a unified store type that combines all stores
interface UnifiedStore {
  // From gameStore (coordinator)
  day: number;
  hour: number;
  incursionStrength: number;
  containmentWards: number;
  initialized: boolean;
  tick: () => void;
  resetGame: () => void;
  gatherMana: () => void;
  startNewLoop: () => void;
  
  // From manaStore
  rawMana: number;
  meditateTicks: number;
  totalManaGathered: number;
  elements: Record<string, { current: number; max: number; unlocked: boolean }>;
  setRawMana: (amount: number) => void;
  addRawMana: (amount: number, max: number) => void;
  spendRawMana: (amount: number) => boolean;
  convertMana: (element: string, amount: number) => boolean;
  unlockElement: (element: string, cost: number) => boolean;
  craftComposite: (target: string, recipe: string[]) => boolean;
  
  // From skillStore
  skills: Record<string, number>;
  skillProgress: Record<string, number>;
  skillUpgrades: Record<string, string[]>;
  skillTiers: Record<string, number>;
  paidStudySkills: Record<string, number>;
  currentStudyTarget: { type: 'skill' | 'spell' | 'blueprint'; id: string; progress: number; required: number } | null;
  parallelStudyTarget: { type: 'skill' | 'spell' | 'blueprint'; id: string; progress: number; required: number } | null;
  setSkillLevel: (skillId: string, level: number) => void;
  startStudyingSkill: (skillId: string, rawMana: number) => { started: boolean; cost: number };
  startStudyingSpell: (spellId: string, rawMana: number, studyTime: number) => { started: boolean; cost: number };
  cancelStudy: (retentionBonus: number) => void;
  selectSkillUpgrade: (skillId: string, upgradeId: string) => void;
  deselectSkillUpgrade: (skillId: string, upgradeId: string) => void;
  commitSkillUpgrades: (skillId: string, upgradeIds: string[]) => void;
  tierUpSkill: (skillId: string) => void;
  getSkillUpgradeChoices: (skillId: string, milestone: 5 | 10) => { available: Array<{ id: string; name: string; desc: string; milestone: 5 | 10; effect: { type: string; stat?: string; value?: number; specialId?: string } }>; selected: string[] };
  
  // From prestigeStore
  loopCount: number;
  insight: number;
  totalInsight: number;
  loopInsight: number;
  prestigeUpgrades: Record<string, number>;
  memorySlots: number;
  pactSlots: number;
  memories: Array<{ skillId: string; level: number; tier: number; upgrades: string[] }>;
  defeatedGuardians: number[];
  signedPacts: number[];
  pactRitualFloor: number | null;
  pactRitualProgress: number;
  doPrestige: (id: string) => void;
  addMemory: (memory: { skillId: string; level: number; tier: number; upgrades: string[] }) => void;
  removeMemory: (skillId: string) => void;
  clearMemories: () => void;
  startPactRitual: (floor: number, rawMana: number) => boolean;
  cancelPactRitual: () => void;
  removePact: (floor: number) => void;
  defeatGuardian: (floor: number) => void;
  
  // From combatStore
  currentFloor: number;
  floorHP: number;
  floorMaxHP: number;
  maxFloorReached: number;
  activeSpell: string;
  currentAction: GameAction;
  castProgress: number;
  spells: Record<string, { learned: boolean; level: number; studyProgress?: number }>;
  setAction: (action: GameAction) => void;
  setSpell: (spellId: string) => void;
  learnSpell: (spellId: string) => void;
  advanceFloor: () => void;
  
  // From uiStore
  log: string[];
  paused: boolean;
  gameOver: boolean;
  victory: boolean;
  addLog: (message: string) => void;
  togglePause: () => void;
  setPaused: (paused: boolean) => void;
  setGameOver: (gameOver: boolean, victory?: boolean) => void;
}

interface GameContextValue {
  // Unified store for backward compatibility
  store: UnifiedStore;
  
  // Individual stores for direct access if needed
  skillStore: ReturnType<typeof useSkillStore.getState>;
  manaStore: ReturnType<typeof useManaStore.getState>;
  prestigeStore: ReturnType<typeof usePrestigeStore.getState>;
  uiStore: ReturnType<typeof useUIStore.getState>;
  combatStore: ReturnType<typeof useCombatStore.getState>;
  
  // Computed effects from upgrades
  upgradeEffects: ReturnType<typeof computeEffects>;
  
  // Derived stats
  maxMana: number;
  baseRegen: number;
  clickMana: number;
  floorElem: string;
  floorElemDef: ElementDef | undefined;
  isGuardianFloor: boolean;
  currentGuardian: GuardianDef | undefined;
  activeSpellDef: SpellDef | undefined;
  meditationMultiplier: number;
  incursionStrength: number;
  studySpeedMult: number;
  studyCostMult: number;
  
  // Effective regen calculations
  effectiveRegenWithSpecials: number;
  manaCascadeBonus: number;
  manaWaterfallBonus: number;
  effectiveRegen: number;
  
  // Has special flags
  hasManaWaterfall: boolean;
  hasFlowSurge: boolean;
  hasManaOverflow: boolean;
  hasEternalFlow: boolean;
  
  // DPS calculation
  dps: number;
  
  // Boons
  activeBoons: ReturnType<typeof getBoonBonuses>;
  
  // Helpers
  canCastSpell: (spellId: string) => boolean;
  hasSpecial: (effects: ReturnType<typeof computeEffects>, specialId: string) => boolean;
  SPECIAL_EFFECTS: typeof SPECIAL_EFFECTS;
}

const GameContext = createContext<GameContextValue | null>(null);

export function GameProvider({ children }: { children: ReactNode }) {
  // Get all individual stores
  const gameStore = useGameStore();
  const skillState = useSkillStore();
  const manaState = useManaStore();
  const prestigeState = usePrestigeStore();
  const uiState = useUIStore();
  const combatState = useCombatStore();
  
  // Create unified store object for backward compatibility
  const unifiedStore = useMemo<UnifiedStore>(() => ({
    // From gameStore
    day: gameStore.day,
    hour: gameStore.hour,
    incursionStrength: gameStore.incursionStrength,
    containmentWards: gameStore.containmentWards,
    initialized: gameStore.initialized,
    tick: gameStore.tick,
    resetGame: gameStore.resetGame,
    gatherMana: gameStore.gatherMana,
    startNewLoop: gameStore.startNewLoop,
    
    // From manaStore
    rawMana: manaState.rawMana,
    meditateTicks: manaState.meditateTicks,
    totalManaGathered: manaState.totalManaGathered,
    elements: manaState.elements,
    setRawMana: manaState.setRawMana,
    addRawMana: manaState.addRawMana,
    spendRawMana: manaState.spendRawMana,
    convertMana: manaState.convertMana,
    unlockElement: manaState.unlockElement,
    craftComposite: manaState.craftComposite,
    
    // From skillStore
    skills: skillState.skills,
    skillProgress: skillState.skillProgress,
    skillUpgrades: skillState.skillUpgrades,
    skillTiers: skillState.skillTiers,
    paidStudySkills: skillState.paidStudySkills,
    currentStudyTarget: skillState.currentStudyTarget,
    parallelStudyTarget: skillState.parallelStudyTarget,
    setSkillLevel: skillState.setSkillLevel,
    startStudyingSkill: skillState.startStudyingSkill,
    startStudyingSpell: skillState.startStudyingSpell,
    cancelStudy: skillState.cancelStudy,
    selectSkillUpgrade: skillState.selectSkillUpgrade,
    deselectSkillUpgrade: skillState.deselectSkillUpgrade,
    commitSkillUpgrades: skillState.commitSkillUpgrades,
    tierUpSkill: skillState.tierUpSkill,
    getSkillUpgradeChoices: skillState.getSkillUpgradeChoices,
    
    // From prestigeStore
    loopCount: prestigeState.loopCount,
    insight: prestigeState.insight,
    totalInsight: prestigeState.totalInsight,
    loopInsight: prestigeState.loopInsight,
    prestigeUpgrades: prestigeState.prestigeUpgrades,
    memorySlots: prestigeState.memorySlots,
    pactSlots: prestigeState.pactSlots,
    memories: prestigeState.memories,
    defeatedGuardians: prestigeState.defeatedGuardians,
    signedPacts: prestigeState.signedPacts,
    pactRitualFloor: prestigeState.pactRitualFloor,
    pactRitualProgress: prestigeState.pactRitualProgress,
    doPrestige: prestigeState.doPrestige,
    addMemory: prestigeState.addMemory,
    removeMemory: prestigeState.removeMemory,
    clearMemories: prestigeState.clearMemories,
    startPactRitual: prestigeState.startPactRitual,
    cancelPactRitual: prestigeState.cancelPactRitual,
    removePact: prestigeState.removePact,
    defeatGuardian: prestigeState.defeatGuardian,
    
    // From combatStore
    currentFloor: combatState.currentFloor,
    floorHP: combatState.floorHP,
    floorMaxHP: combatState.floorMaxHP,
    maxFloorReached: combatState.maxFloorReached,
    activeSpell: combatState.activeSpell,
    currentAction: combatState.currentAction,
    castProgress: combatState.castProgress,
    spells: combatState.spells,
    setAction: combatState.setAction,
    setSpell: combatState.setSpell,
    learnSpell: combatState.learnSpell,
    advanceFloor: combatState.advanceFloor,
    
    // From uiStore
    log: uiState.logs,
    paused: uiState.paused,
    gameOver: uiState.gameOver,
    victory: uiState.victory,
    addLog: uiState.addLog,
    togglePause: uiState.togglePause,
    setPaused: uiState.setPaused,
    setGameOver: uiState.setGameOver,
  }), [gameStore, skillState, manaState, prestigeState, uiState, combatState]);
  
  // Computed effects from upgrades
  const upgradeEffects = useMemo(
    () => computeEffects(skillState.skillUpgrades || {}, skillState.skillTiers || {}),
    [skillState.skillUpgrades, skillState.skillTiers]
  );
  
  // Create a minimal state object for compute functions
  const stateForCompute = useMemo(() => ({
    skills: skillState.skills,
    prestigeUpgrades: prestigeState.prestigeUpgrades,
    skillUpgrades: skillState.skillUpgrades,
    skillTiers: skillState.skillTiers,
    signedPacts: prestigeState.signedPacts,
    rawMana: manaState.rawMana,
    meditateTicks: manaState.meditateTicks,
    incursionStrength: gameStore.incursionStrength,
  }), [skillState, prestigeState, manaState, gameStore.incursionStrength]);
  
  // Derived stats
  const maxMana = useMemo(
    () => computeMaxMana(stateForCompute, upgradeEffects),
    [stateForCompute, upgradeEffects]
  );
  
  const baseRegen = useMemo(
    () => computeRegen(stateForCompute, upgradeEffects),
    [stateForCompute, upgradeEffects]
  );
  
  const clickMana = useMemo(() => computeClickMana(stateForCompute), [stateForCompute]);
  
  // Floor element from combat store
  const floorElem = useMemo(() => getFloorElement(combatState.currentFloor), [combatState.currentFloor]);
  const floorElemDef = ELEMENTS[floorElem];
  const isGuardianFloor = !!GUARDIANS[combatState.currentFloor];
  const currentGuardian = GUARDIANS[combatState.currentFloor];
  const activeSpellDef = SPELLS_DEF[combatState.activeSpell];
  
  const meditationMultiplier = useMemo(
    () => getMeditationBonus(manaState.meditateTicks, skillState.skills, upgradeEffects.meditationEfficiency),
    [manaState.meditateTicks, skillState.skills, upgradeEffects.meditationEfficiency]
  );
  
  const incursionStrength = useMemo(
    () => getIncursionStrength(gameStore.day, gameStore.hour),
    [gameStore.day, gameStore.hour]
  );
  
  const studySpeedMult = useMemo(
    () => getStudySpeedMultiplier(skillState.skills),
    [skillState.skills]
  );
  
  const studyCostMult = useMemo(
    () => getStudyCostMultiplier(skillState.skills),
    [skillState.skills]
  );
  
  // Effective regen calculations
  const effectiveRegenWithSpecials = baseRegen * (1 - incursionStrength);
  
  const manaCascadeBonus = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_CASCADE)
    ? Math.floor(maxMana / 100) * 0.1
    : 0;
  
  const manaWaterfallBonus = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_WATERFALL)
    ? Math.floor(maxMana / 100) * 0.25
    : 0;
  
  const effectiveRegen = (effectiveRegenWithSpecials + manaCascadeBonus + manaWaterfallBonus) * meditationMultiplier;
  
  // Has special flags for UI
  const hasManaWaterfall = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_WATERFALL);
  const hasFlowSurge = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.FLOW_SURGE);
  const hasManaOverflow = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_OVERFLOW);
  const hasEternalFlow = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.ETERNAL_FLOW);
  
  // Active boons
  const activeBoons = useMemo(
    () => getBoonBonuses(prestigeState.signedPacts),
    [prestigeState.signedPacts]
  );
  
  // DPS calculation - based on active spell, attack speed, and damage
  const dps = useMemo(() => {
    if (!activeSpellDef) return 0;
    const baseDmg = calcDamage(
      { skills: skillState.skills, signedPacts: prestigeState.signedPacts },
      combatState.activeSpell,
      floorElem
    );
    const dmgWithEffects = baseDmg * upgradeEffects.baseDamageMultiplier + upgradeEffects.baseDamageBonus;
    const attackSpeed = (1 + (skillState.skills.quickCast || 0) * 0.05) * upgradeEffects.attackSpeedMultiplier;
    const castSpeed = activeSpellDef.castSpeed || 1;
    return dmgWithEffects * attackSpeed * castSpeed;
  }, [activeSpellDef, skillState.skills, prestigeState.signedPacts, floorElem, upgradeEffects, combatState.activeSpell]);
  
  // Helper functions
  const canCastSpell = (spellId: string): boolean => {
    const spell = SPELLS_DEF[spellId];
    if (!spell) return false;
    return canAffordSpellCost(spell.cost, manaState.rawMana, manaState.elements);
  };
  
  const value: GameContextValue = {
    store: unifiedStore,
    skillStore: skillState,
    manaStore: manaState,
    prestigeStore: prestigeState,
    uiStore: uiState,
    combatStore: combatState,
    upgradeEffects,
    maxMana,
    baseRegen,
    clickMana,
    floorElem,
    floorElemDef,
    isGuardianFloor,
    currentGuardian,
    activeSpellDef,
    meditationMultiplier,
    incursionStrength,
    studySpeedMult,
    studyCostMult,
    effectiveRegenWithSpecials,
    manaCascadeBonus,
    manaWaterfallBonus,
    effectiveRegen,
    hasManaWaterfall,
    hasFlowSurge,
    hasManaOverflow,
    hasEternalFlow,
    dps,
    activeBoons,
    canCastSpell,
    hasSpecial,
    SPECIAL_EFFECTS,
  };

  return <GameContext.Provider value={value}>{children}</GameContext.Provider>;
}

export function useGameContext() {
  const context = useContext(GameContext);
  if (!context) {
    throw new Error('useGameContext must be used within a GameProvider');
  }
  return context;
}

GameProvider.displayName = "GameProvider";

// Re-export useGameLoop for convenience
export { useGameLoop };
