import { describe, it, expect, beforeEach, vi } from 'vitest';
import { useCombatStore } from '../stores/combatStore';
import { useDisciplineStore } from '../stores/discipline-slice';
import { createDefaultCombatState } from '../stores/combat-reset';
import { computeChannelStats } from '../stores/combat-channel';

// ─── Helpers ──────────────────────────────────────────────────────────────────

function resetCombatStore() {
  useCombatStore.setState({
    currentFloor: 1,
    floorHP: 100,
    floorMaxHP: 100,
    maxFloorReached: 1,
    activeSpell: 'manaBolt',
    currentAction: 'meditate',
    castProgress: 0,
    spireMode: false,
    currentRoom: { roomType: 'combat', enemies: [] },
    clearedFloors: {},
    climbDirection: null,
    isDescending: false,
    golemancy: { activeGolems: [], lastSummonFloor: 0, golemDesigns: {}, golemLoadout: [] },
    equipmentSpellStates: [],
    comboHitCount: 0,
    floorHitCount: 0,
    spells: { manaBolt: { learned: true, level: 1, studyProgress: 0 } },
    activityLog: [],
    achievements: { unlocked: [], progress: {} },
    totalSpellsCast: 0,
    totalDamageDealt: 0,
    totalCraftsCompleted: 0,
  });
}

function resetDisciplineStore() {
  useDisciplineStore.setState({
    activeDisciplines: [],
    disciplineXP: {},
    disciplineLevels: {},
    concurrentLimit: 1,
  });
}

// ─── Tests ────────────────────────────────────────────────────────────────────

describe('createDefaultCombatState channel stats', () => {
  beforeEach(() => {
    resetCombatStore();
    resetDisciplineStore();
  });

  it('should use base channel stats when no disciplines are active', () => {
    const state = createDefaultCombatState(1);
    // Base values from combat-channel.ts
    expect(state.channelSpeedMultiplier).toBe(1.5);
    expect(state.channelDrainRate).toBe(0.08);
  });

  it('should match computeChannelStats output', () => {
    const state = createDefaultCombatState(1);
    const expected = computeChannelStats();
    expect(state.channelSpeedMultiplier).toBe(expected.speedMultiplier);
    expect(state.channelDrainRate).toBe(expected.drainRate);
  });

  it('should reset isChanneling to false', () => {
    useCombatStore.setState({ isChanneling: true });
    const state = createDefaultCombatState(1);
    expect(state.isChanneling).toBe(false);
  });

  it('should produce channel stats consistent with combat tick computation', () => {
    // The key invariant: after resetCombat, the channel stats in the store
    // should match what computeChannelStats() returns, so the first tick
    // doesn't see a mismatch.
    const defaults = createDefaultCombatState(1);
    const expected = computeChannelStats();
    expect(defaults.channelSpeedMultiplier).toBeCloseTo(expected.speedMultiplier, 10);
    expect(defaults.channelDrainRate).toBeCloseTo(expected.drainRate, 10);
  });
});

describe('resetCombat preserves channel stat consistency', () => {
  beforeEach(() => {
    resetCombatStore();
    resetDisciplineStore();
  });

  it('should set channel stats from computeChannelStats on reset', () => {
    // Simulate combat tick having written modified channel stats
    useCombatStore.setState({
      channelSpeedMultiplier: 2.0,
      channelDrainRate: 0.12,
    });

    // Reset combat
    useCombatStore.getState().resetCombat(1);

    // After reset, stats should be the discipline-computed defaults
    const expected = computeChannelStats();
    expect(useCombatStore.getState().channelSpeedMultiplier).toBe(expected.speedMultiplier);
    expect(useCombatStore.getState().channelDrainRate).toBe(expected.drainRate);
  });

  it('should not leave isChanneling true after reset', () => {
    useCombatStore.setState({ isChanneling: true });
    useCombatStore.getState().resetCombat(1);
    expect(useCombatStore.getState().isChanneling).toBe(false);
  });
});
