// ─── Derived Stats Hooks ───────────────────────────────────────────────────────
// Custom hooks for computing derived game stats from the store

import { useMemo } from 'react';
import { useGameStore } from '../stores/gameStore';
import { useManaStore } from '../stores/manaStore';
import { useCombatStore } from '../stores/combatStore';
import { usePrestigeStore } from '../stores/prestigeStore';
import { computeEffects } from '../effects/upgrade-effects';
import {
  computeMaxMana,
  computeRegen,
  computeClickMana,
  getMeditationBonus,
  getIncursionStrength,
  getFloorElement,
  calcDamage,
  getElementalBonus,
} from '../utils';
import { computePactMultiplier, computePactInsightMultiplier } from '../utils/pact-utils';
import { ELEMENTS, GUARDIANS, SPELLS_DEF, getStudySpeedMultiplier, getStudyCostMultiplier, HOURS_PER_TICK, TICK_MS } from '../constants';
import { hasSpecial, SPECIAL_EFFECTS } from '../effects/special-effects';

/**
 * Hook for all mana-related derived stats
 */
export function useManaStats() {
  const skills = useGameStore((s) => s.skills);
  const skillUpgrades = useGameStore((s) => s.skillUpgrades);
  const skillTiers = useGameStore((s) => s.skillTiers);
  const prestigeUpgrades = usePrestigeStore((s) => s.prestigeUpgrades);
  const rawMana = useManaStore((s) => s.rawMana);
  const meditateTicks = useManaStore((s) => s.meditateTicks);
  const day = useGameStore((s) => s.day);
  const hour = useGameStore((s) => s.hour);

  const upgradeEffects = useMemo(
    () => computeEffects(skillUpgrades || {}, skillTiers || {}),
    [skillUpgrades, skillTiers]
  );

  const maxMana = useMemo(
    () => computeMaxMana({ skills, prestigeUpgrades, skillUpgrades, skillTiers }, upgradeEffects),
    [skills, prestigeUpgrades, skillUpgrades, skillTiers, upgradeEffects]
  );

  const baseRegen = useMemo(
    () => computeRegen({ skills, prestigeUpgrades, skillUpgrades, skillTiers }, upgradeEffects),
    [skills, prestigeUpgrades, skillUpgrades, skillTiers, upgradeEffects]
  );

  const clickMana = useMemo(
    () => computeClickMana({ skills }),
    [skills]
  );

  const meditationMultiplier = useMemo(
    () => getMeditationBonus(meditateTicks, skills, upgradeEffects.meditationEfficiency),
    [meditateTicks, skills, upgradeEffects.meditationEfficiency]
  );

  const incursionStrength = useMemo(
    () => getIncursionStrength(day, hour),
    [day, hour]
  );

  // Effective regen with incursion penalty
  const effectiveRegenWithSpecials = baseRegen * (1 - incursionStrength);

  // Mana Cascade bonus
  const manaCascadeBonus = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_CASCADE)
    ? Math.floor(maxMana / 100) * 0.1
    : 0;

  // Mana Waterfall bonus
  const manaWaterfallBonus = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_WATERFALL)
    ? Math.floor(maxMana / 100) * 0.25
    : 0;

  // Final effective regen
  const effectiveRegen = (effectiveRegenWithSpecials + manaCascadeBonus + manaWaterfallBonus) * meditationMultiplier;

  return {
    upgradeEffects,
    maxMana,
    baseRegen,
    clickMana,
    meditationMultiplier,
    incursionStrength,
    effectiveRegenWithSpecials,
    manaCascadeBonus,
    manaWaterfallBonus,
    effectiveRegen,
    hasSteadyStream: hasSpecial(upgradeEffects, SPECIAL_EFFECTS.STEADY_STREAM),
    hasManaTorrent: hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_TORRENT),
    hasDesperateWells: hasSpecial(upgradeEffects, SPECIAL_EFFECTS.DESPERATE_WELLS),
    hasManaEcho: hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_ECHO),
    hasManaWaterfall: hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_WATERFALL),
    hasFlowSurge: hasSpecial(upgradeEffects, SPECIAL_EFFECTS.FLOW_SURGE),
    hasManaOverflow: hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_OVERFLOW),
    hasEternalFlow: hasSpecial(upgradeEffects, SPECIAL_EFFECTS.ETERNAL_FLOW),
  };
}

/**
 * Hook for combat-related derived stats
 */
export function useCombatStats() {
  const skills = useGameStore((s) => s.skills);
  const signedPacts = usePrestigeStore((s) => s.signedPacts);
  const currentFloor = useCombatStore((s) => s.currentFloor);
  const activeSpell = useCombatStore((s) => s.activeSpell);
  const { upgradeEffects } = useManaStats();

  const floorElem = useMemo(
    () => getFloorElement(currentFloor),
    [currentFloor]
  );

  const floorElemDef = useMemo(
    () => ELEMENTS[floorElem],
    [floorElem]
  );

  const isGuardianFloor = useMemo(
    () => !!GUARDIANS[currentFloor],
    [currentFloor]
  );

  const currentGuardian = useMemo(
    () => GUARDIANS[currentFloor],
    [currentFloor]
  );

  const activeSpellDef = useMemo(
    () => SPELLS_DEF[activeSpell],
    [activeSpell]
  );

  const pactMultiplier = useMemo(
    () => computePactMultiplier({ signedPacts }),
    [signedPacts]
  );

  const pactInsightMultiplier = useMemo(
    () => computePactInsightMultiplier({ signedPacts }),
    [signedPacts]
  );

  // DPS calculation
  const dps = useMemo(() => {
    if (!activeSpellDef) return 0;

    const spellCastSpeed = activeSpellDef.castSpeed || 1;
    const quickCastBonus = 1 + (skills.quickCast || 0) * 0.05;
    const attackSpeedMult = upgradeEffects.attackSpeedMultiplier;
    const totalCastSpeed = spellCastSpeed * quickCastBonus * attackSpeedMult;

    const damagePerCast = calcDamage({ skills, signedPacts }, activeSpell, floorElem);
    const castsPerSecond = totalCastSpeed * HOURS_PER_TICK / (TICK_MS / 1000);

    return damagePerCast * castsPerSecond;
  }, [activeSpellDef, skills, signedPacts, activeSpell, floorElem, upgradeEffects.attackSpeedMultiplier]);

  // Damage breakdown for display
  const damageBreakdown = useMemo(() => {
    if (!activeSpellDef) return null;

    const baseDmg = activeSpellDef.dmg;
    const combatTrainBonus = (skills.combatTrain || 0) * 5;
    const arcaneFuryMult = 1 + (skills.arcaneFury || 0) * 0.1;
    const elemMasteryMult = 1 + (skills.elementalMastery || 0) * 0.15;
    const guardianBaneMult = isGuardianFloor ? (1 + (skills.guardianBane || 0) * 0.2) : 1;
    const precisionChance = (skills.precision || 0) * 0.05;

    // Calculate elemental bonus
    const elemBonus = getElementalBonus(activeSpellDef.elem, floorElem);
    let elemBonusText = '';
    if (activeSpellDef.elem !== 'raw' && floorElem) {
      if (activeSpellDef.elem === floorElem) {
        elemBonusText = '+25% same element';
      } else if (elemBonus === 1.5) {
        elemBonusText = '+50% super effective';
      }
    }

    return {
      base: baseDmg,
      combatTrainBonus,
      arcaneFuryMult,
      elemMasteryMult,
      guardianBaneMult,
      pactMult: pactMultiplier,
      precisionChance,
      elemBonus,
      elemBonusText,
      total: calcDamage({ skills, signedPacts }, activeSpell, floorElem),
    };
  }, [activeSpellDef, skills, signedPacts, activeSpell, floorElem, isGuardianFloor, pactMultiplier]);

  return {
    floorElem,
    floorElemDef,
    isGuardianFloor,
    currentGuardian,
    activeSpellDef,
    pactMultiplier,
    pactInsightMultiplier,
    dps,
    damageBreakdown,
  };
}

/**
 * Hook for study-related derived stats
 */
export function useStudyStats() {
  const skills = useGameStore((s) => s.skills);
  const skillUpgrades = useGameStore((s) => s.skillUpgrades);
  const skillTiers = useGameStore((s) => s.skillTiers);

  const studySpeedMult = useMemo(
    () => getStudySpeedMultiplier(skills),
    [skills]
  );

  const studyCostMult = useMemo(
    () => getStudyCostMultiplier(skills),
    [skills]
  );

  const upgradeEffects = useMemo(
    () => computeEffects(skillUpgrades || {}, skillTiers || {}),
    [skillUpgrades, skillTiers]
  );

  const effectiveStudySpeedMult = studySpeedMult * upgradeEffects.studySpeedMultiplier;

  return {
    studySpeedMult,
    studyCostMult,
    effectiveStudySpeedMult,
    hasParallelStudy: hasSpecial(upgradeEffects, SPECIAL_EFFECTS.PARALLEL_STUDY),
  };
}
