import { expect } from "@esm-bundle/chai";
import { RosterManager } from "../../src/managers/RosterManager.js";

describe("Manager: RosterManager", () => {
  let manager;

  beforeEach(() => {
    manager = new RosterManager();
  });

  it("CoA 1: Should initialize with empty roster and graveyard", () => {
    expect(manager.roster).to.be.an("array").that.is.empty;
    expect(manager.graveyard).to.be.an("array").that.is.empty;
    expect(manager.rosterLimit).to.equal(12);
  });

  it("CoA 2: recruitUnit should add unit to roster with generated ID and character name", async () => {
    const unitData = {
      classId: "CLASS_VANGUARD",
      name: "Vanguard", // This will become className
      stats: { hp: 100 },
    };

    const newUnit = await manager.recruitUnit(unitData);

    expect(newUnit).to.exist;
    expect(newUnit.id).to.match(/^UNIT_\d+_\d+$/);
    expect(newUnit.classId).to.equal("CLASS_VANGUARD");
    // Name should be a generated character name, not the class name
    expect(newUnit.name).to.be.a("string");
    expect(newUnit.name).to.not.equal("Vanguard");
    expect(newUnit.className).to.equal("Vanguard");
    expect(newUnit.status).to.equal("READY");
    expect(newUnit.history).to.deep.equal({ missions: 0, kills: 0 });
    expect(manager.roster).to.have.length(1);
    expect(manager.roster[0]).to.equal(newUnit);
  });

  it("CoA 3: recruitUnit should return false when roster is full", async () => {
    // Fill roster to limit
    for (let i = 0; i < manager.rosterLimit; i++) {
      await manager.recruitUnit({ classId: "CLASS_VANGUARD", name: `Unit ${i}` });
    }

    const result = await manager.recruitUnit({ classId: "CLASS_VANGUARD", name: "Extra" });

    expect(result).to.be.false;
    expect(manager.roster).to.have.length(manager.rosterLimit);
  });

  it("CoA 4: handleUnitDeath should move unit to graveyard and remove from roster", async () => {
    const unit = await manager.recruitUnit({
      classId: "CLASS_VANGUARD",
      name: "Vanguard",
    });
    const unitId = unit.id;

    manager.handleUnitDeath(unitId);

    expect(manager.roster).to.be.empty;
    expect(manager.graveyard).to.have.length(1);
    expect(manager.graveyard[0].id).to.equal(unitId);
    expect(manager.graveyard[0].status).to.equal("DEAD");
  });

  it("CoA 5: handleUnitDeath should do nothing if unit not found", async () => {
    await manager.recruitUnit({ classId: "CLASS_VANGUARD", name: "Vanguard" });

    manager.handleUnitDeath("NONEXISTENT_ID");

    expect(manager.roster).to.have.length(1);
    expect(manager.graveyard).to.be.empty;
  });

  it("CoA 6: getDeployableUnits should return only READY units", async () => {
    const ready1 = await manager.recruitUnit({
      classId: "CLASS_VANGUARD",
      name: "Vanguard",
    });
    const ready2 = await manager.recruitUnit({
      classId: "CLASS_TINKER",
      name: "Tinker",
    });

    // Manually set a unit to INJURED
    manager.roster[0].status = "INJURED";

    const deployable = manager.getDeployableUnits();

    expect(deployable).to.have.length(1);
    expect(deployable[0].id).to.equal(ready2.id);
    expect(deployable[0].status).to.equal("READY");
  });

  it("CoA 7: load should restore roster and graveyard from save data", () => {
    const saveData = {
      roster: [
        { id: "UNIT_1", classId: "CLASS_VANGUARD", name: "Valerius", className: "Vanguard", status: "READY" },
        { id: "UNIT_2", classId: "CLASS_TINKER", name: "Aria", className: "Tinker", status: "INJURED" },
      ],
      graveyard: [{ id: "UNIT_3", classId: "CLASS_VANGUARD", name: "Kael", className: "Vanguard", status: "DEAD" }],
    };

    manager.load(saveData);

    expect(manager.roster).to.have.length(2);
    expect(manager.graveyard).to.have.length(1);
    expect(manager.roster[0].id).to.equal("UNIT_1");
    expect(manager.graveyard[0].id).to.equal("UNIT_3");
  });

  it("CoA 10: load should restore classMastery and activeClassId progression data", () => {
    const saveData = {
      roster: [
        {
          id: "UNIT_1",
          classId: "CLASS_VANGUARD",
          name: "Valerius",
          className: "Vanguard",
          status: "READY",
          activeClassId: "CLASS_VANGUARD",
          classMastery: {
            CLASS_VANGUARD: {
              level: 5,
              xp: 250,
              skillPoints: 3,
              unlockedNodes: ["ROOT", "NODE_1"],
            },
          },
        },
      ],
      graveyard: [],
    };

    manager.load(saveData);

    expect(manager.roster[0].classMastery).to.exist;
    expect(manager.roster[0].classMastery.CLASS_VANGUARD.level).to.equal(5);
    expect(manager.roster[0].classMastery.CLASS_VANGUARD.xp).to.equal(250);
    expect(manager.roster[0].classMastery.CLASS_VANGUARD.skillPoints).to.equal(3);
    expect(manager.roster[0].classMastery.CLASS_VANGUARD.unlockedNodes).to.include("ROOT");
    expect(manager.roster[0].activeClassId).to.equal("CLASS_VANGUARD");
  });

  it("CoA 11: save should preserve classMastery and activeClassId progression data", async () => {
    const unit = await manager.recruitUnit({ classId: "CLASS_VANGUARD", name: "Vanguard" });
    
    // Add progression data
    unit.activeClassId = "CLASS_VANGUARD";
    unit.classMastery = {
      CLASS_VANGUARD: {
        level: 3,
        xp: 150,
        skillPoints: 2,
        unlockedNodes: ["ROOT"],
      },
    };

    const saved = manager.save();

    expect(saved.roster[0].classMastery).to.exist;
    expect(saved.roster[0].classMastery.CLASS_VANGUARD.level).to.equal(3);
    expect(saved.roster[0].classMastery.CLASS_VANGUARD.xp).to.equal(150);
    expect(saved.roster[0].classMastery.CLASS_VANGUARD.skillPoints).to.equal(2);
    expect(saved.roster[0].classMastery.CLASS_VANGUARD.unlockedNodes).to.include("ROOT");
    expect(saved.roster[0].activeClassId).to.equal("CLASS_VANGUARD");
  });

  it("CoA 8: save should serialize roster and graveyard", async () => {
    await manager.recruitUnit({ classId: "CLASS_VANGUARD", name: "Vanguard" });
    await manager.recruitUnit({ classId: "CLASS_TINKER", name: "Tinker" });
    const unitId = manager.roster[0].id;
    manager.handleUnitDeath(unitId);

    const saved = manager.save();

    expect(saved).to.have.property("roster");
    expect(saved).to.have.property("graveyard");
    expect(saved.roster).to.have.length(1);
    expect(saved.graveyard).to.have.length(1);
    expect(saved.roster[0].name).to.be.a("string"); // Generated character name
    expect(saved.graveyard[0].id).to.equal(unitId);
  });

  it("CoA 9: clear should reset roster and graveyard", async () => {
    await manager.recruitUnit({ classId: "CLASS_VANGUARD", name: "Vanguard" });
    manager.handleUnitDeath(manager.roster[0].id);

    manager.clear();

    expect(manager.roster).to.be.empty;
    expect(manager.graveyard).to.be.empty;
  });
});

