/**
 * Perk Item Data Model
 *
 * Defines the data schema for perks (feats/talents) in Vagabond RPG.
 * Characters gain 1 perk at odd levels (1, 3, 5, 7, 9).
 *
 * Perks have prerequisites that may include:
 * - Minimum stat values
 * - Training in specific skills
 * - Knowledge of specific spells
 * - Other perks
 *
 * @extends VagabondItemBase
 */
import VagabondItemBase from "./base-item.mjs";

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

    return {
      ...baseSchema,

      // Prerequisites
      prerequisites: new fields.SchemaField({
        // Stat requirements (e.g., { might: 4, dexterity: 3 })
        stats: new fields.SchemaField({
          might: new fields.NumberField({ integer: true, nullable: true, initial: null }),
          dexterity: new fields.NumberField({ integer: true, nullable: true, initial: null }),
          awareness: new fields.NumberField({ integer: true, nullable: true, initial: null }),
          reason: new fields.NumberField({ integer: true, nullable: true, initial: null }),
          presence: new fields.NumberField({ integer: true, nullable: true, initial: null }),
          luck: new fields.NumberField({ integer: true, nullable: true, initial: null }),
        }),

        // Required skill training (array of skill IDs)
        trainedSkills: new fields.ArrayField(new fields.StringField(), { initial: [] }),

        // Required spells (array of spell names)
        spells: new fields.ArrayField(new fields.StringField(), { initial: [] }),

        // Required other perks (array of perk names)
        perks: new fields.ArrayField(new fields.StringField(), { initial: [] }),

        // Custom prerequisite text (for complex requirements)
        custom: new fields.StringField({ required: false, blank: true }),
      }),

      // Mechanical effects (as Active Effect changes)
      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: [] }
      ),

      // Is this perk passive or does it require activation?
      passive: new fields.BooleanField({ initial: true }),

      // Usage tracking (for limited-use perks)
      uses: new fields.SchemaField({
        value: new fields.NumberField({ integer: true, initial: 0 }),
        max: new fields.NumberField({ integer: true, initial: 0 }),
        per: new fields.StringField({ initial: "" }), // "short", "long", "day", ""
      }),

      // Luck System Integration
      // Cost in Luck points to activate this perk
      luckCost: new fields.NumberField({
        integer: true,
        initial: 0,
        min: 0,
      }),

      // Does this perk grant Luck when triggered?
      grantsLuck: new fields.NumberField({
        integer: true,
        initial: 0,
        min: 0,
      }),

      // Ritual System (specific perks are rituals with extended casting)
      isRitual: new fields.BooleanField({ initial: false }),

      // Ritual duration in minutes (10, 60, etc.)
      ritualDuration: new fields.NumberField({
        integer: true,
        initial: 0,
        min: 0,
      }),

      // Ritual components required (text description)
      ritualComponents: new fields.StringField({
        required: false,
        blank: true,
      }),

      // Tags for categorization
      tags: new fields.ArrayField(new fields.StringField(), { initial: [] }),
    };
  }

  /**
   * Check if a character meets this perk's prerequisites.
   *
   * @param {Object} actorData - The actor's system data
   * @returns {Object} Result with 'met' boolean and 'missing' array of unmet requirements
   */
  checkPrerequisites(actorData) {
    const missing = [];

    // Check stat requirements
    for (const [stat, required] of Object.entries(this.prerequisites.stats)) {
      if (required !== null && required > 0) {
        const actorStat = actorData.stats?.[stat]?.value || 0;
        if (actorStat < required) {
          missing.push(`${stat.charAt(0).toUpperCase() + stat.slice(1)} ${required}`);
        }
      }
    }

    // Check skill training requirements
    for (const skillId of this.prerequisites.trainedSkills) {
      const skill = actorData.skills?.[skillId];
      if (!skill?.trained) {
        missing.push(`Trained in ${skillId}`);
      }
    }

    // Note: Spell and perk prerequisites would need item checks on the parent actor
    // These are tracked but validation requires access to actor items

    if (this.prerequisites.spells.length > 0) {
      missing.push(`Spells: ${this.prerequisites.spells.join(", ")}`);
    }

    if (this.prerequisites.perks.length > 0) {
      missing.push(`Perks: ${this.prerequisites.perks.join(", ")}`);
    }

    if (this.prerequisites.custom) {
      missing.push(this.prerequisites.custom);
    }

    return {
      met: missing.length === 0,
      missing,
    };
  }

  /**
   * Get a formatted string of prerequisites for display.
   *
   * @returns {string} Formatted prerequisite string
   */
  getPrerequisiteString() {
    const parts = [];

    // Stat requirements
    for (const [stat, required] of Object.entries(this.prerequisites.stats)) {
      if (required !== null && required > 0) {
        const abbr = stat.substring(0, 3).toUpperCase();
        parts.push(`${abbr} ${required}`);
      }
    }

    // Skill training
    for (const skill of this.prerequisites.trainedSkills) {
      parts.push(`Trained: ${skill}`);
    }

    // Spells
    for (const spell of this.prerequisites.spells) {
      parts.push(`Spell: ${spell}`);
    }

    // Perks
    for (const perk of this.prerequisites.perks) {
      parts.push(`Perk: ${perk}`);
    }

    // Custom
    if (this.prerequisites.custom) {
      parts.push(this.prerequisites.custom);
    }

    return parts.length > 0 ? parts.join(", ") : "None";
  }

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

    data.prerequisites = this.getPrerequisiteString();
    data.passive = this.passive;

    return data;
  }
}
