/**
 * Class Item Data Model
 *
 * Defines the data schema for character classes in Vagabond RPG.
 * Classes are designed as draggable items that can be added to characters.
 *
 * Each class provides:
 * - Key stat recommendation
 * - Action style (casting skill for casters)
 * - Preferred combat zone
 * - Training grants (skills trained)
 * - Starting equipment pack
 * - Progression table (level 1-10)
 *
 * @extends VagabondItemBase
 */
import VagabondItemBase from "./base-item.mjs";

export default class ClassData extends VagabondItemBase {
  /**
   * Define the schema for class items.
   *
   * @returns {Object} The schema definition
   */
  static defineSchema() {
    const fields = foundry.data.fields;
    const baseSchema = super.defineSchema();

    return {
      ...baseSchema,

      // Key stat recommendation for this class
      keyStat: new fields.StringField({
        required: true,
        initial: "might",
      }),

      // Action style / casting skill (for casters)
      // e.g., "arcana" for Wizard, "mysticism" for Druid, "influence" for Sorcerer
      actionStyle: new fields.StringField({
        required: false,
        blank: true,
      }),

      // Preferred combat zone
      zone: new fields.StringField({
        required: true,
        initial: "frontline",
        choices: ["frontline", "midline", "backline"],
      }),

      // Weapon proficiencies granted by this class
      // e.g., ["melee"], ["melee", "ranged"], or [] for none
      weaponTraining: new fields.ArrayField(
        new fields.StringField({ choices: ["melee", "ranged"] }),
        { initial: [] }
      ),

      // Skills trained by this class - supports fixed grants and player choices
      // Each entry is either: {type: "fixed", skills: ["craft"]} or {type: "choice", skills: ["detect", "sneak"], count: 2}
      // Empty skills array for "choice" means any skill
      skillTraining: new fields.ArrayField(
        new fields.SchemaField({
          type: new fields.StringField({
            required: true,
            choices: ["fixed", "choice"],
            initial: "fixed",
          }),
          skills: new fields.ArrayField(new fields.StringField(), { initial: [] }),
          count: new fields.NumberField({ integer: true, initial: 1 }),
        }),
        { initial: [] }
      ),

      // Legacy field - kept for backwards compatibility, prefer skillTraining
      trainedSkills: new fields.ArrayField(new fields.StringField(), { initial: [] }),

      // Starting equipment pack description
      startingPack: new fields.HTMLField({ required: false, blank: true }),

      // Is this a spellcasting class?
      isCaster: new fields.BooleanField({ initial: false }),

      // Progression table - level-by-level benefits
      progression: new fields.ArrayField(
        new fields.SchemaField({
          level: new fields.NumberField({ integer: true, min: 1, max: 10 }),
          mana: new fields.NumberField({ integer: true, initial: 0 }),
          castingMax: new fields.NumberField({ integer: true, initial: 0 }),
          spellsKnown: new fields.NumberField({ integer: true, initial: 0 }),
          features: new fields.ArrayField(new fields.StringField(), { initial: [] }),
        }),
        { initial: [] }
      ),

      // Class features - detailed definitions
      features: new fields.ArrayField(
        new fields.SchemaField({
          name: new fields.StringField({ required: true }),
          level: new fields.NumberField({ integer: true, min: 1, max: 10 }),
          description: new fields.HTMLField({ required: true }),
          passive: new fields.BooleanField({ initial: true }),
          // Active Effect changes this feature applies
          changes: new fields.ArrayField(
            new fields.SchemaField({
              key: new fields.StringField({ required: true }),
              mode: new fields.NumberField({ integer: true, initial: 2 }),
              value: new fields.StringField({ required: true }),
            }),
            { initial: [] }
          ),
          // Choice features - features that require player selection
          requiresChoice: new fields.BooleanField({ initial: false }),
          choiceType: new fields.StringField({ required: false, blank: true }), // "perk", "spell", etc.
          choiceFilter: new fields.ObjectField({ required: false }), // Filter criteria for choices
        }),
        { initial: [] }
      ),

      // Resource this class uses (if any) - e.g., "Studied Dice" for Alchemist
      customResource: new fields.SchemaField({
        name: new fields.StringField({ required: false }),
        max: new fields.StringField({ required: false }), // Can be a formula like "@level"
      }),
    };
  }

  /**
   * Get the features available at a given level.
   *
   * @param {number} level - Character level to check
   * @returns {Array} Array of features available at or before this level
   */
  getFeaturesAtLevel(level) {
    return this.features.filter((f) => f.level <= level);
  }

  /**
   * Get the progression entry for a given level.
   *
   * @param {number} level - Character level to check
   * @returns {Object|null} Progression data for the level
   */
  getProgressionAtLevel(level) {
    return this.progression.find((p) => p.level === level) || null;
  }

  /**
   * Get cumulative mana pool at a given level.
   *
   * @param {number} level - Character level
   * @returns {number} Total mana pool
   */
  getManaAtLevel(level) {
    let totalMana = 0;
    for (const prog of this.progression) {
      if (prog.level <= level) {
        totalMana += prog.mana || 0;
      }
    }
    return totalMana;
  }

  /**
   * Get cumulative casting max at a given level.
   * Casting max increases are cumulative across levels.
   *
   * @param {number} level - Character level
   * @returns {number} Casting max (max mana per spell)
   */
  getCastingMaxAtLevel(level) {
    let castingMax = 0;
    for (const prog of this.progression) {
      if (prog.level <= level) {
        castingMax += prog.castingMax || 0;
      }
    }
    return castingMax;
  }

  /**
   * Get chat card data for displaying class information.
   *
   * @returns {Object} Chat card data
   */
  getChatData() {
    const data = super.getChatData();

    data.keyStat = this.keyStat;
    data.zone = this.zone;
    data.isCaster = this.isCaster;
    data.weaponTraining = this.weaponTraining;
    data.skillTraining = this.skillTraining;
    data.trainedSkills = this.trainedSkills; // Legacy

    return data;
  }
}
