import { beforeEach, describe, expect, it } from "vitest";
import { createClassInventory } from "./healers";
import { HOCKEY_ARENA_MAX_Z, HOCKEY_ARENA_MIN_Z } from "./hockeyHealing";
import { useGameStore } from "./store";

function disableBossPressure() {
  useGameStore.setState((state) => ({
    boss: { ...state.boss, nextMeleeAt: 999 },
    additionalBosses: state.additionalBosses.map((entry) => ({
      ...entry,
      boss: { ...entry.boss, nextMeleeAt: 999 },
      motion: { ...entry.motion, nextMechanicAt: 999 },
    })),
    bossMotion: { ...state.bossMotion, nextMechanicAt: 999 },
  }));
}

describe("Aether Assault store integration", () => {
  beforeEach(() => {
    useGameStore.getState().configureHealer(
      "priest",
      "Aelia",
      createClassInventory("priest"),
      ["bulldrome", "broodfang-spider"],
      "aether-assault",
    );
    useGameStore.getState().startEncounter();
    disableBossPressure();
  });

  it("keeps auto-fire running while the healer casts and uses the global cooldown", () => {
    useGameStore.setState((state) => ({
      party: state.party.map((member) => member.id === "brann" ? { ...member, hp: member.hp - 40 } : member),
    }));
    useGameStore.getState().selectMember("brann");

    expect(useGameStore.getState().castAbility("ability1")).toBe(true);
    expect(useGameStore.getState().activeCast).not.toBeNull();
    useGameStore.getState().tick(0.21);

    const state = useGameStore.getState();
    expect(state.activeCast).not.toBeNull();
    expect(state.globalCooldownUntil).toBeGreaterThan(state.time);
    expect(state.aetherAssault.playerShots.length).toBeGreaterThanOrEqual(2);
  });

  it("lets the healer traverse the full rink", () => {
    useGameStore.getState().setPlayerPosition([0, -100]);
    expect(useGameStore.getState().playerPosition[1]).toBeCloseTo(HOCKEY_ARENA_MIN_Z + 0.65);

    useGameStore.getState().setPlayerPosition([0, 100]);
    expect(useGameStore.getState().playerPosition[1]).toBeCloseTo(HOCKEY_ARENA_MAX_Z - 0.65);
  });

  it("applies mitigated ship damage only to the healer and grants hit protection", () => {
    const before = useGameStore.getState();
    const healerPosition = before.partyPositions.aelia;
    const initialHp = before.party.map((member) => member.hp);
    useGameStore.setState((state) => ({
      barrier: { ...state.barrier, kind: "barrier", center: [...healerPosition], expiresAt: 10 },
      aetherAssault: {
        ...state.aetherAssault,
        killStreak: 5,
        multiplier: 1.25,
        enemyShots: [{ id: 900, position: [...healerPosition], velocity: [0, 0] }],
      },
    }));

    useGameStore.getState().tick(0.01);
    const afterFirst = useGameStore.getState();
    expect(afterFirst.party[0].hp).toBeCloseTo(initialHp[0] - 7);
    expect(afterFirst.party.slice(1).map((member) => member.hp)).toEqual(initialHp.slice(1));
    expect(afterFirst.aetherAssault.killStreak).toBe(0);
    expect(afterFirst.aetherAssault.multiplier).toBe(1);

    useGameStore.setState((state) => ({
      aetherAssault: {
        ...state.aetherAssault,
        enemyShots: [{ id: 901, position: [...state.partyPositions.aelia], velocity: [0, 0] }],
      },
    }));
    useGameStore.getState().tick(0.1);
    expect(useGameStore.getState().party[0].hp).toBeCloseTo(afterFirst.party[0].hp);
  });

  it("keeps boss replacement independent from arcade waves", () => {
    const originalInstance = useGameStore.getState().bossInstanceId;
    useGameStore.setState((state) => ({ boss: { ...state.boss, hp: 1 } }));
    useGameStore.getState().tick(2);
    expect(useGameStore.getState().endlessBossKills).toBe(1);
    expect(useGameStore.getState().boss.hp).toBe(0);

    useGameStore.getState().tick(2);
    useGameStore.getState().tick(1.3);

    const state = useGameStore.getState();
    expect(state.endlessBossKills).toBe(1);
    expect(state.boss.hp).toBeGreaterThan(0);
    expect(state.bossInstanceId).not.toBe(originalInstance);
    expect(state.aetherAssault.status).toBe("live");
  });

  it("pauses arcade simulation, resets a run, and ends only on party wipe", () => {
    useGameStore.getState().tick(0.21);
    const beforePause = useGameStore.getState().aetherAssault;
    useGameStore.getState().setPaused(true);
    useGameStore.getState().tick(1);
    expect(useGameStore.getState().aetherAssault).toBe(beforePause);

    useGameStore.getState().setPaused(false);
    useGameStore.setState((state) => ({
      party: state.party.map((member) => ({ ...member, hp: 0 })),
    }));
    useGameStore.getState().tick(0.01);
    expect(useGameStore.getState().phase).toBe("defeat");

    useGameStore.getState().restart();
    const restarted = useGameStore.getState();
    expect(restarted.phase).toBe("briefing");
    expect(restarted.aetherAssault.wave).toBe(1);
    expect(restarted.aetherAssault.score).toBe(0);
    expect(restarted.aetherAssault.ships).toHaveLength(8);
  });
});
