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

import { useMemo } from 'react';
import { useGameStore } from '../stores/gameStore';
import { useCraftingStore } from '../stores/craftingStore';
import { useManaStore } from '../stores/manaStore';
import { useCombatStore } from '../stores/combatStore';
import { usePrestigeStore } from '../stores/prestigeStore';
import { useAttunementStore } from '../stores/attunementStore';
import { useDisciplineStore } from '../stores/discipline-slice';
import { computeEffects } from '../effects/upgrade-effects';
import {
  computeMaxMana,
  computeRegen,
  computeClickMana,
  getMeditationBonus,
  getIncursionStrength,
  getFloorElement,
  calcDamage,
  getElementalBonus,
  getBoonBonuses,
} from '../utils';
import { computeEquipmentEffects } from '../effects';
import { computePactMultiplier, computePactInsightMultiplier } from '../utils/pact-utils';

import { ELEMENTS, SPELLS_DEF, getStudySpeedMultiplier, getStudyCostMultiplier, HOURS_PER_TICK, TICK_MS } from '../constants';
import { getGuardianForFloor } from '../data/guardian-encounters';
import { hasSpecial, SPECIAL_EFFECTS } from '../effects/special-effects';
import { computeDisciplineEffects } from '../effects/discipline-effects';

/**
 * Hook for all mana-related derived stats
 */
export function useManaStats() {
  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 attunements = useAttunementStore((s) => s.attunements);

  const disciplines = useDisciplineStore((s) => s.disciplines);

  const disciplineEffects = useMemo(
    () => computeDisciplineEffects(),
    [disciplines]
  );

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

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

  const baseRegen = useMemo(
    () => computeRegen({ prestigeUpgrades, attunements } as any, upgradeEffects),
    [prestigeUpgrades, upgradeEffects, attunements]
  );

  const clickMana = useMemo(
    () => computeClickMana(disciplineEffects),
    [disciplineEffects]
  );

  const meditationCap = 5.0 + disciplineEffects.meditationCapBonus;
  const meditationMultiplier = useMemo(
    () => getMeditationBonus(meditateTicks, upgradeEffects.meditationEfficiency, disciplineEffects.meditationCapBonus),
    [meditateTicks, upgradeEffects.meditationEfficiency, disciplineEffects.meditationCapBonus]
  );

  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,
    meditationCap,
    incursionStrength,
    effectiveRegenWithSpecials,
    manaCascadeBonus,
    manaWaterfallBonus,
    effectiveRegen,
    disciplineMaxManaBonus: disciplineEffects.bonuses.maxManaBonus || 0,
    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 signedPacts = usePrestigeStore((s) => s.signedPacts);
  const currentFloor = useCombatStore((s) => s.currentFloor);
  const activeSpell = useCombatStore((s) => s.activeSpell);
  const { upgradeEffects } = useManaStats();
  const equipmentInstances = useCraftingStore((s) => s.equipmentInstances);
  const equippedInstances = useCraftingStore((s) => s.equippedInstances);

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

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

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

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

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

  const pactInterferenceMitigation = usePrestigeStore((s) => s.prestigeUpgrades.pactInterferenceMitigation || 0);

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

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

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

    const spellCastSpeed = activeSpellDef.castSpeed || 1;
    const quickCastBonus = 1;
    const attackSpeedMult = upgradeEffects.attackSpeedMultiplier;
    const totalCastSpeed = spellCastSpeed * quickCastBonus * attackSpeedMult;

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

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

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

    const baseDmg = activeSpellDef.dmg;
    const combatTrainBonus = 0;
    const arcaneFuryMult = 1;
    const elemMasteryMult = 1;
    const guardianBaneMult = 1;
    const precisionChance = 0;

    // 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({ signedPacts }, activeSpell, floorElem),
    };
  }, [activeSpellDef, signedPacts, activeSpell, floorElem, isGuardianFloor, pactMultiplier]);

  // Crit chance: sum equipment bonus (decimal) + pact boon bonus (percentage points) + upgrade bonus (decimal)
  const critChance = useMemo(() => {
    const equipEffects = computeEquipmentEffects(equipmentInstances, equippedInstances);
    const equipCritBonus = equipEffects.bonuses.critChance || 0;
    const boons = getBoonBonuses(signedPacts);
    const boonCritChance = boons.critChance / 100; // Convert percentage points to decimal
    const upgradeCritBonus = upgradeEffects.critChanceBonus || 0;
    return equipCritBonus + boonCritChance + upgradeCritBonus;
  }, [equipmentInstances, equippedInstances, signedPacts, upgradeEffects.critChanceBonus]);

  // Crit damage: base multiplier (1.5) + pact boon bonus (percentage points)
  const critDamage = useMemo(() => {
    const boons = getBoonBonuses(signedPacts);
    return (upgradeEffects.critDamageMultiplier || 1.5) + boons.critDamage / 100;
  }, [signedPacts, upgradeEffects.critDamageMultiplier]);

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

/**
 * Hook for study-related derived stats
 */
export function useStudyStats() {
  const studySpeedMult = useMemo(
    () => getStudySpeedMultiplier(),
    []
  );

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

  const upgradeEffects = useMemo(
    () => computeEffects(),
    []
  );

  const effectiveStudySpeedMult = studySpeedMult * upgradeEffects.studySpeedMultiplier;

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