// ─── Combat State Types ────────────────────────────────────────────────────────
// Shared types for combat store and combat actions to avoid circular dependency

import type { GameAction, SpellState, FloorState, GolemancyState, ActivityLogEntry, AchievementState, EquipmentSpellState, ActivityEventType, RuntimeActiveGolem, EnemyState, EquipmentInstance, SerializedGolemDesign } from '../types';
import type { ActiveInvocation } from '../utils/invocation-utils';

/** Signature for the advanceRoomOrFloor callback to break circular dependency */
export type AdvanceRoomFn = (get: () => CombatStore, set: (s: Partial<CombatState>) => void) => void;

// ─── Combat State (data only) ─────────────────────────────────────────────────

export interface CombatState {
  // Floor state
  currentFloor: number;
  floorHP: number;
  floorMaxHP: number;
  maxFloorReached: number;

  // Action state
  activeSpell: string;
  currentAction: GameAction;
  castProgress: number;

  // Spire mode
  spireMode: boolean;

  // Room system for special floors
  currentRoom: FloorState;

  // Spire climbing state
  clearedFloors: Record<number, boolean>;
  climbDirection: 'up' | 'down' | null;
  isDescending: boolean;

  // ─── Spec: Run identity (climbing spec §4.2, §7) ──────────────────────
  /** Unique run ID, generated on spire entry. Used as seed component: floor × 12345 + runId */
  runId: number;

  // ─── Spec: Room navigation (climbing spec §6) ───────────────────────────
  /** Floor the player entered at (= 1 + spireKey × 2) */
  startFloor: number;
  /** Floor the player must reach on descent to exit (= startFloor) */
  exitFloor: number;
  /** 0-indexed room within currentFloor */
  currentRoomIndex: number;
  /** Total rooms on currentFloor (deterministic via seed) */
  roomsPerFloor: number;

  // ─── Spec: Descent tracking (climbing spec §6) ──────────────────────────
  /** Snapshot of peak floor/room when descent was initiated */
  descentPeak: { floor: number; roomIndex: number } | null;
  /** Per-room reset rolls, lazily populated on descent. Key = "floor:roomIndex" */
  roomResetState: Record<string, boolean>;
  /** Tracks which floor:roomIndex pairs were cleared on ascent */
  clearedRooms: Record<string, boolean>;
  /** True when player has reached exitFloor R0 during descent */
  isDescentComplete: boolean;

  // Golemancy (summoned golems)
  golemancy: GolemancyState;

  // Equipment spell states for multi-casting
  equipmentSpellStates: EquipmentSpellState[];

  // Per-weapon cast progress records (spec §3.1, D-01 fix)
  // Key: 'primary' for active spell, or instanceId for equipment spells
  weaponCastProgress: Record<string, number>;

  // Combat special effect tracking
  comboHitCount: number;
  floorHitCount: number;

  // Melee sword progress accumulators (spec §3.1)
  meleeSwordProgress: Record<string, number>;

  // Guardian defensive state (shield, barrier, regen)
  guardianShield: number;
  guardianShieldMax: number;
  guardianBarrier: number;
  guardianBarrierMax: number;

  // Spells
  spells: Record<string, SpellState>;

  // Activity Log (for Spire Mode UI)
  activityLog: ActivityLogEntry[];

  // Achievements
  achievements: AchievementState;

  // Stats tracking
  totalSpellsCast: number;
  totalDamageDealt: number;
  totalCraftsCompleted: number;

  // Invocation system
  invocationCharge: number;
  activeInvocation: ActiveInvocation | null;

  // ─── Room Enchantments ─────────────────────────────────────────────────
  /** Carryover coverage from previous room (for resonant-stamps perk). Resets on spire exit. */
  lastRoomCoverage: number;

  // ─── Transference Channel ──────────────────────────────────────────────
  isChanneling: boolean;
  channelSpeedMultiplier: number;
  channelDrainRate: number;
}

// ─── Combat Actions ───────────────────────────────────────────────────────────

export interface CombatActions {
  setCurrentFloor: (floor: number) => void;
  advanceFloor: () => void;
  setFloorHP: (hp: number) => void;
  setMaxFloorReached: (floor: number) => void;

  setAction: (action: GameAction) => void;
  setSpell: (spellId: string) => void;
  setCastProgress: (progress: number) => void;

  // Room state
  setCurrentRoom: (room: FloorState) => void;

  // Spire climbing
  setClimbDirection: (direction: 'up' | 'down' | null) => void;
  setClearedFloor: (floor: number, cleared: boolean) => void;
  setIsDescending: (descending: boolean) => void;
  climbDownFloor: () => void;
  exitSpireMode: () => void;
  startClimbUp: () => void;
  startClimbDown: () => void;
  startPracticing: () => void;
  stopPracticing: () => void;

  // ─── Spec: New descent actions (climbing spec §2.2) ─────────────────────
  /** Snapshot peak floor/room, set climbDirection = 'down', begin reverse traversal */
  enterDescentMode: () => void;
  /** Move to next room/floor (ascending) or previous room/floor (descending) */
  advanceRoomOrFloor: () => void;
  /** Check per-room reset on descent entry; auto-skip or re-generate enemies */
  onEnterRoomDescend: () => void;
  /** Grant discipline XP scaled by floor, then advance */
  onEnterLibraryRoom: () => void;
  /** Tick non-combat room progress (called from game tick pipeline) */
  tickNonCombatRoom: (hours: number, advance: AdvanceRoomFn) => void;
  /** Skip current non-combat room (library, recovery, treasure) */
  skipNonCombatRoom: (advance: AdvanceRoomFn) => void;
  /** Stay 1 hour longer in library or recovery room */
  stayLongerInRoom: () => void;

  // Golemancy
  addGolemDesign: (design: SerializedGolemDesign) => void;
  removeGolemDesign: (designId: string) => void;
  toggleGolemLoadoutEntry: (designId: string) => void;

  // Spells
  learnSpell: (spellId: string) => void;
  setSpellState: (spellId: string, state: Partial<SpellState>) => void;

  // Activity Log
  addActivityLog: (eventType: ActivityEventType, message: string, details?: ActivityLogEntry['details']) => void;

  // Stats
  incrementSpellsCast: () => void;
  addDamageDealt: (damage: number) => void;
  incrementCraftsCompleted: () => void;

  // Spire mode
  enterSpireMode: () => void;

  // Combat tick
  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>,
  ) => {
    rawMana: number;
    elements: Record<string, { current: number; max: number; unlocked: boolean }>;
    logMessages: string[];
    totalManaGathered: number;
    currentFloor: number;
    floorHP: number;
    floorMaxHP: number;
    maxFloorReached: number;
    castProgress: number;
    equipmentSpellStates: EquipmentSpellState[];
    activeGolems: RuntimeActiveGolem[];
    meleeSwordProgress: Record<string, number>;
    currentRoom: FloorState;
  };

  // Invocation
  resetInvocationState: () => void;

  // Transference Channel
  startChanneling: () => void;
  stopChanneling: () => void;

  // Reset
  resetCombat: (startFloor: number, spellsToKeep?: string[]) => void;

  // Room Enchantments
  setLastRoomCoverage: (value: number) => void;
}

// ─── Combined Combat Store Type ───────────────────────────────────────────────

export type CombatStore = CombatState & CombatActions;
