import { describe, expect, it } from "vitest";
import { createClassInventory } from "./healers";
import { AVAILABLE_BOSS_IDS } from "./bossCatalog";
import { canAddBossToEncounter } from "./bossSelection";
import { useGameStore } from "./store";
import type { BossId } from "./types";

interface BattleResult {
  phase: ReturnType<typeof useGameStore.getState>["phase"];
  time: number;
  damageBySource: ReturnType<typeof useGameStore.getState>["partyCombat"]["combatants"];
}

function simulateControlledBattle(bossIds: readonly [BossId, BossId], maxSeconds = 200): BattleResult {
  useGameStore.getState().configureHealer("priest", "Aelia", createClassInventory("priest"), bossIds);
  useGameStore.getState().startEncounter();

  while (useGameStore.getState().phase === "combat" && useGameStore.getState().time < maxSeconds) {
    useGameStore.setState((state) => ({
      party: state.party.map((member) => ({ ...member, hp: member.maxHp, absorb: 10_000 })),
    }));
    useGameStore.getState().tick(0.1);
  }

  const state = useGameStore.getState();
  return { phase: state.phase, time: state.time, damageBySource: state.partyCombat.combatants };
}

describe("full-mechanics dual-boss battle simulations", () => {
  const combinations: readonly (readonly [BossId, BossId])[] = AVAILABLE_BOSS_IDS.flatMap((first, index) =>
    AVAILABLE_BOSS_IDS.slice(index + 1)
      .filter((second) => canAddBossToEncounter([first], second))
      .map((second) => [first, second] as const),
  );

  it.each(combinations)("party rotations defeat %s + %s", (first, second) => {
    const result = simulateControlledBattle([first, second]);
    expect(result.phase).toBe("victory");
    expect(result.time).toBeGreaterThanOrEqual(50);
    expect(result.time).toBeLessThanOrEqual(100);
    for (const memberId of ["brann", "nia", "orin", "vale"] as const) expect(result.damageBySource[memberId].damageDone).toBeGreaterThan(0);
  });
});
