import { describe, expect, it } from "vitest";
import { freshParty } from "./data";
import {
  createHealerMechanicState,
  healTargetAndBeacon,
  isBeaconOfLightTarget,
  placeOrRewindTimeAnchor,
  resolveTimeLoop,
  startTimeLoop,
} from "./healerMechanics";

describe("shared healer mechanics", () => {
  it("identifies only the active Beacon of Light target", () => {
    const mechanic = {
      ...createHealerMechanicState("paladin"),
      beaconTargetId: "nia" as const,
      beaconExpiresAt: 10,
    };
    expect(isBeaconOfLightTarget("nia", mechanic, 9.99)).toBe(true);
    expect(isBeaconOfLightTarget("brann", mechanic, 9.99)).toBe(false);
    expect(isBeaconOfLightTarget("nia", mechanic, 10)).toBe(false);
  });

  it("echoes a direct heal without healing dead or duplicate beacon targets", () => {
    const party = freshParty("paladin").map((member) => member.id === "brann"
      ? { ...member, hp: 50 }
      : member.id === "nia"
        ? { ...member, hp: 20 }
        : member);
    const mechanic = {
      ...createHealerMechanicState("paladin"),
      beaconTargetId: "brann" as const,
      beaconExpiresAt: 10,
    };

    const result = healTargetAndBeacon(party, 2, 30, mechanic, 1);
    expect(result.party[2].hp).toBe(50);
    expect(result.party[1].hp).toBe(62);
    expect(result.directHealing).toBe(30);
    expect(result.beaconHealing).toBe(12);
    expect(party[1].hp).toBe(50);
  });

  it("replaces an anchor on a new target and rewinds only its recorded target", () => {
    const party = freshParty("chronomancer").map((member) => member.id === "brann" ? { ...member, hp: 90 } : member);
    const mechanic = createHealerMechanicState("chronomancer");
    const anchored = placeOrRewindTimeAnchor(party, 1, mechanic, 1);
    const damaged = anchored.party.map((member) => member.id === "brann" ? { ...member, hp: 35 } : member);
    const rewound = placeOrRewindTimeAnchor(damaged, 1, anchored.mechanic, 2);

    expect(rewound.party[1].hp).toBe(90);
    expect(rewound.restored).toBe(55);
    expect(rewound.mechanic.temporalAnchor).toBeNull();
  });

  it("resolves a party snapshot once without resurrecting defeated allies", () => {
    const party = freshParty("chronomancer");
    const mechanic = startTimeLoop(party, createHealerMechanicState("chronomancer"), 5);
    const damaged = party.map((member) => member.id === "brann"
      ? { ...member, hp: 40 }
      : member.id === "nia"
        ? { ...member, hp: 0 }
        : member);
    const early = resolveTimeLoop(damaged, mechanic, 4.9);
    const resolved = resolveTimeLoop(early.party, early.mechanic, 5);

    expect(early.party[1].hp).toBe(40);
    expect(resolved.party[1].hp).toBe(150);
    expect(resolved.party[2].hp).toBe(0);
    expect(resolved.mechanic.timeLoop).toBeNull();
  });
});
