// ─── Combat Actions ─────────────────────────────────────────────────────────────
// Extracted combat logic from combatStore.ts

import { SPELLS_DEF, GUARDIANS, HOURS_PER_TICK } from '../constants';
import type { CombatState } from './combat-state.types';
import type { SpellState } from '../types';
import { getFloorMaxHP, getFloorElement, calcDamage, canAffordSpellCost, deductSpellCost } from '../utils';
import { usePrestigeStore } from './prestigeStore';
import { computeDisciplineEffects } from '../effects/discipline-effects';
import { useDisciplineStore } from './discipline-slice';

export function processCombatTick(
  get: () => CombatState,
  set: (state: Partial<CombatState>) => void,
  rawMana: number,
  elements: Record<string, { current: number; max: number; unlocked: boolean }>,
  maxMana: number,
  attackSpeedMult: number,
  onFloorCleared: (floor: number, wasGuardian: boolean) => void,
  onDamageDealt: (damage: number) => {
    rawMana: number;
    elements: Record<string, { current: number; max: number; unlocked: boolean }>;
    modifiedDamage?: number;
  },
) {
  const state = get();
  const logMessages: string[] = [];
  let totalManaGathered = 0;

  if (state.currentAction !== 'climb') {
    return { rawMana, elements, logMessages, totalManaGathered };
  }

  const spellId = state.activeSpell;
  const spellDef = SPELLS_DEF[spellId];
  if (!spellDef) {
    return { rawMana, elements, logMessages, totalManaGathered };
  }

  // Compute discipline bonuses once per tick
  const disciplineEffects = computeDisciplineEffects(useDisciplineStore.getState() as any);

  // Calculate cast speed (no skill bonus)
  const totalAttackSpeed = attackSpeedMult;
  const spellCastSpeed = spellDef.castSpeed || 1;
  const progressPerTick = HOURS_PER_TICK * spellCastSpeed * totalAttackSpeed;

  let castProgress = (state.castProgress || 0) + progressPerTick;
  let floorHP = state.floorHP;
  let currentFloor = state.currentFloor;
  let floorMaxHP = state.floorMaxHP;

  // Process complete casts for active spell
  while (castProgress >= 1 && canAffordSpellCost(spellDef.cost, rawMana, elements)) {
    // Deduct spell cost
    const afterCost = deductSpellCost(spellDef.cost, rawMana, elements);
    rawMana = afterCost.rawMana;
    elements = afterCost.elements;
    // Calculate base damage
    const floorElement = getFloorElement(currentFloor);
    const damage = calcDamage(
      { skills: {}, signedPacts: usePrestigeStore.getState().signedPacts },
      spellId,
      floorElement,
      disciplineEffects,
    );

    // Let gameStore apply damage modifiers (executioner, berserker)
    const result = onDamageDealt(damage);
    rawMana = result.rawMana;
    elements = result.elements;
    const finalDamage = result.modifiedDamage || damage;

    // Apply damage
    floorHP = Math.max(0, floorHP - finalDamage);
    castProgress -= 1;

    // Check if floor is cleared
    if (floorHP <= 0) {
      const wasGuardian = GUARDIANS[currentFloor];
      onFloorCleared(currentFloor, !!wasGuardian);

      currentFloor = Math.min(currentFloor + 1, 100);
      floorMaxHP = getFloorMaxHP(currentFloor);
      floorHP = floorMaxHP;
      castProgress = 0;

      if (wasGuardian) {
        logMessages.push(`⚔️ ${wasGuardian.name} defeated!`);
      } else if (currentFloor % 5 === 0) {
        logMessages.push(`🏰 Floor ${currentFloor - 1} cleared!`);
      }
    }
  }

  // Process equipment spell states (for progress bars in UI)
  const updatedEquipmentSpellStates = [...state.equipmentSpellStates];
  for (let i = 0; i < updatedEquipmentSpellStates.length; i++) {
    const eSpell = updatedEquipmentSpellStates[i];
    const eSpellDef = SPELLS_DEF[eSpell.spellId];
    if (!eSpellDef) continue;

    // Calculate progress for this equipment spell
    const eSpellCastSpeed = eSpellDef.castSpeed || 1;
    const eProgressPerTick = HOURS_PER_TICK * eSpellCastSpeed * totalAttackSpeed;
    let eCastProgress = (eSpell.castProgress || 0) + eProgressPerTick;

    // Process complete casts for equipment spells
    while (eCastProgress >= 1 && canAffordSpellCost(eSpellDef.cost, rawMana, elements)) {
      // Deduct cost
      const eAfterCost = deductSpellCost(eSpellDef.cost, rawMana, elements);
      rawMana = eAfterCost.rawMana;
      elements = eAfterCost.elements;
      // Calculate damage
      const eFloorElement = getFloorElement(currentFloor);
      const eDamage = calcDamage(
        { skills: {}, signedPacts: usePrestigeStore.getState().signedPacts },
        eSpell.spellId,
        eFloorElement,
        disciplineEffects,
      );

      const eResult = onDamageDealt(eDamage);
      rawMana = eResult.rawMana;
      elements = eResult.elements;
      const eFinalDamage = eResult.modifiedDamage || eDamage;

      floorHP = Math.max(0, floorHP - eFinalDamage);
      eCastProgress -= 1;

      if (floorHP <= 0) break; // Floor cleared, stop processing
    }

    // Update equipment spell state
    updatedEquipmentSpellStates[i] = { ...eSpell, castProgress: eCastProgress % 1 };
  }

  set({
    currentFloor,
    floorHP,
    floorMaxHP: getFloorMaxHP(currentFloor),
    maxFloorReached: Math.max(state.maxFloorReached, currentFloor),
    castProgress,
    equipmentSpellStates: updatedEquipmentSpellStates,
  });

  return { rawMana, elements, logMessages, totalManaGathered };
}

// Helper function to create initial spells
export function makeInitialSpells(spellsToKeep: string[] = []): Record<string, SpellState> {
  const startSpells: Record<string, SpellState> = {
    manaBolt: { learned: true, level: 1, studyProgress: 0 },
  };

  // Add kept spells
  for (const spellId of spellsToKeep) {
    startSpells[spellId] = { learned: true, level: 1, studyProgress: 0 };
  }

  return startSpells;
}
