/**
 * @typedef {import("../units/types.js").ExplorerData} ExplorerData
 * @typedef {import("../units/types.js").RosterSaveData} RosterSaveData
 */

/**
 * RosterManager.js
 * Manages the persistent pool of Explorer units (The Barracks).
 * Handles recruitment, death, and selection for missions.
 * @class
 */

export class RosterManager {
  constructor() {
    /** @type {ExplorerData[]} */
    this.roster = []; // List of active Explorer objects (Data only)
    /** @type {ExplorerData[]} */
    this.graveyard = []; // List of dead units
    /** @type {ExplorerData[]} */
    this.candidates = []; // Pool of recruitable units
    /** @type {number} */
    this.rosterLimit = 12;
  }

  /**
   * Initializes the roster from saved data.
   * @param {RosterSaveData} saveData - Saved roster data
   */
  load(saveData) {
    this.roster = saveData.roster || [];
    this.graveyard = saveData.graveyard || [];
    this.candidates = saveData.candidates || [];

    // DATA MIGRATION: Fix legacy portrait paths
    const fixPortrait = (unit) => {
      if (unit.portrait && unit.portrait.includes("class_")) {
        // Replace "class_" with "" in the filename part
        // e.g. assets/images/portraits/class_weaver.png -> assets/images/portraits/weaver.png
        // Use regex to be safe: /class_([a-z]+)\.png/
        unit.portrait = unit.portrait.replace(/class_/g, "");
      }
    };

    this.roster.forEach(fixPortrait);
    this.candidates.forEach(fixPortrait);
  }

  /**
   * Serializes for save file.
   * @returns {RosterSaveData} - Serialized roster data
   */
  save() {
    return {
      roster: this.roster,
      graveyard: this.graveyard,
      candidates: this.candidates,
    };
  }

  /**
   * Adds a new unit to the roster.
   * @param {Partial<ExplorerData>} unitData - The unit definition (Class, Name, Stats)
   * @returns {Promise<ExplorerData | false>} - The recruited unit or false if roster is full
   */
  async recruitUnit(unitData) {
    if (this.roster.length >= this.rosterLimit) {
      console.warn("Roster full. Cannot recruit.");
      return false;
    }

    // Lazy import name generator only when needed
    const { generateCharacterName } = await import("../utils/nameGenerator.js");

    // Generate a character name and set className from the existing name property
    const characterName = generateCharacterName();
    const className = unitData.name || unitData.className; // Use name as className if provided

    const newUnit = {
      id: `UNIT_${Date.now()}_${Math.floor(Math.random() * 1000)}`,
      ...unitData,
      name: characterName, // Generated character name
      className: className, // Class name (e.g., "Vanguard", "Weaver")
      status: "READY", // READY, INJURED, DEPLOYED
      history: { missions: 0, kills: 0 },
    };

    this.roster.push(newUnit);
    return newUnit;
  }

  /**
   * Marks a unit as dead and moves them to the graveyard.
   * @param {string} unitId - Unit ID to mark as dead
   */
  handleUnitDeath(unitId) {
    const index = this.roster.findIndex((u) => u.id === unitId);
    if (index > -1) {
      const unit = this.roster[index];
      unit.status = "DEAD";
      this.graveyard.push(unit);
      this.roster.splice(index, 1);
    }
  }

  /**
   * Returns units eligible for a mission.
   * Filters out injured or dead units.
   * @returns {ExplorerData[]} - Array of deployable units
   */
  getDeployableUnits() {
    return this.roster.filter((u) => u.status === "READY");
  }

  /**
   * Clears the roster and graveyard. Used when starting a new game.
   */
  clear() {
    this.graveyard = [];
    this.candidates = [];
  }

  /**
   * Generates a new set of candidates for recruitment.
   * @param {number} count - Number of candidates to generate
   */
  async generateCandidates(count = 3) {
    this.candidates = [];

    // Lazy import name generator
    const { generateCharacterName } = await import("../utils/nameGenerator.js");

    // Available classes (basic pool)
    const classes = [
      "CLASS_VANGUARD",
      "CLASS_WEAVER",
      "CLASS_SCAVENGER",
      "CLASS_TINKER",
    ];

    for (let i = 0; i < count; i++) {
      const randomClass = classes[Math.floor(Math.random() * classes.length)];
      const name = generateCharacterName();

      const candidate = {
        id: `CANDIDATE_${Date.now()}_${i}`,
        name: name,
        className: randomClass, // ID used for lookup
        activeClassId: randomClass,
        level: 1,
        status: "READY",
        hiringCost: 100, // Fixed cost for now
        portrait: `assets/images/portraits/${randomClass
          .replace("CLASS_", "")
          .toLowerCase()}.png`,
      };

      this.candidates.push(candidate);
    }
  }

  /**
   * Hires a candidate, moving them to the roster.
   * @param {string} candidateId
   * @param {Object} wallet - Reference to wallet to deduct funds (if handled here, but manager acts on data)
   * @returns {Promise<boolean>} success
   */
  async hireCandidate(candidateId) {
    if (this.roster.length >= this.rosterLimit) {
      console.warn("Roster full.");
      return false;
    }

    const index = this.candidates.findIndex((c) => c.id === candidateId);
    if (index === -1) return false;

    const candidate = this.candidates[index];

    // Recruit logic specific to candidate -> unit conversion
    // (We can reused recruitUnit but we need to ensure ID is unique/updated if needed, though candidate ID is fine usually)
    // Actually, recruitUnit generates a new ID. Let's use that to be safe and consistent.

    await this.recruitUnit({
      name: candidate.name,
      className: candidate.className,
      activeClassId: candidate.activeClassId,
      portrait: candidate.portrait,
    });

    // Remove from candidates
    this.candidates.splice(index, 1);

    return true;
  }
}
