/**
 * DataModel pour les acteurs de type "character" (personnage).
 * Étend foundry.abstract.TypeDataModel.
 */
import {
  woundSchema,
  combatStatusSchema,
  equipmentSchema,
  attributeSchema,
  abilitiesSchema,
  skillCategoriesSchema,
  skillsSchema
} from "./_shared.mjs"
import { VermineTraits } from "../system/traits.mjs"

export default class VermineCharacterData extends foundry.abstract.TypeDataModel {

  /** @override */
  static LOCALIZATION_PREFIXES = ["VERMINE.character"]

  /** @override */
  static defineSchema() {
    const fields = foundry.data.fields

    return {
      // Blessures (base)
      minorWound: new fields.SchemaField(woundSchema(1, 5)),
      majorWound: new fields.SchemaField(woundSchema(4, 4)),
      deadlyWound: new fields.SchemaField(woundSchema(8, 2)),

      // Statut de combat (base)
      combatStatus: combatStatusSchema("7"),

      // Adaptation (totems humain/adapté)
      adaptation: new fields.SchemaField({
        value: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 1, min: 0, max: 5 }),
        min: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0 }),
        max: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 5, min: 0 }),
        totems: new fields.SchemaField({
          human: new fields.SchemaField({
            value: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 1, min: 0, max: 3 }),
            min: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0 }),
            max: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 3, min: 0 })
          }),
          adapted: new fields.SchemaField({
            value: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 1, min: 0, max: 3 }),
            min: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0 }),
            max: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 3, min: 0 })
          })
        })
      }),

      // Identité
      identity: new fields.SchemaField({
        height: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
        weight: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
        totem: new fields.StringField({ required: true, nullable: false, initial: "" }),
        // Statut de Chaman : débloque l'affichage des Rites chamaniques maîtrisés.
        chaman: new fields.BooleanField({ required: true, initial: false }),
        age: new fields.StringField({ required: true, nullable: false, initial: "15" }),
        ageType: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 2 }),
        profile: new fields.StringField({ required: true, nullable: false, initial: "" }),
        theme: new fields.StringField({ required: true, nullable: false, initial: "" }),
        instincts: new fields.StringField({ required: true, nullable: false, initial: "" }),
        prohibits: new fields.StringField({ required: true, nullable: false, initial: "" }),
        objectives: new fields.StringField({ required: true, nullable: false, initial: "" }),
        relations: new fields.HTMLField({ required: true, initial: "" }),
        biography: new fields.HTMLField({ required: true, initial: "" })
      }),

      // Équipement
      equipment: equipmentSchema(),

      // Attributs (XP, réputation, sang-froid, effort)
      attributes: new fields.SchemaField({
        xp: attributeSchema(0, 0, 10),
        reputation: attributeSchema(0, 0, 10),
        self_control: attributeSchema(0, 0, 10),
        effort: attributeSchema(0, 0, 10)
      }),

      // Expérience (dés, récompenses, évolution, apprentissage)
      experience: new fields.SchemaField({
        dice: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0 }),
        phase: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0 }),
        collective: new fields.SchemaField({
          danger: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0, max: 3 }),
          discoveries: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0, max: 3 }),
          duration: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0, max: 3 })
        }),
        individual: new fields.SchemaField({
          implication: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0, max: 3 }),
          influence: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0, max: 3 }),
          interpretation: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0, max: 3 })
        }),
        evolution: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0 }),
        traumaReward: new fields.BooleanField({ required: true, initial: false }),
        // Bonus de Réserve acquis par apprentissage (s'ajoute au max dérivé)
        reserveBonus: new fields.SchemaField({
          self_control: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0 }),
          effort: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0 })
        }),
        // Perte de Réserves après perte du Fétiche : -1D de max persistant par Réserve
        feticheLoss: new fields.SchemaField({
          self_control: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0 }),
          effort: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0 })
        }),
        // Limites d'apprentissage par phase
        learned: new fields.SchemaField({
          phase: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0 }),
          skill: new fields.BooleanField({ required: true, initial: false }),
          specialty: new fields.BooleanField({ required: true, initial: false }),
          reserve: new fields.BooleanField({ required: true, initial: false }),
          characteristic: new fields.BooleanField({ required: true, initial: false }),
          evolution: new fields.BooleanField({ required: true, initial: false }),
          ability: new fields.BooleanField({ required: true, initial: false }),
          background: new fields.BooleanField({ required: true, initial: false }),
          reputation: new fields.BooleanField({ required: true, initial: false })
        })
      }),

      // Rencontres
      encounters: new fields.ArrayField(new fields.StringField({ required: true, nullable: false, initial: "" })),

      // Caractéristiques (8)
      abilities: abilitiesSchema(),

      // Catégories de compétences
      skill_categories: skillCategoriesSchema(),

      // Compétences (30)
      skills: skillsSchema()
    }
  }

  /** @override */
  prepareDerivedData() {
    super.prepareDerivedData()

    this._setAgeType()
    this._setSelfControlMax()
    this._setEffortMax()
    this._setWoundThresholds()
    this._updateCombatStatus()
  }

  /**
   * Détermine la tranche d'âge (1=jeune, 2=adulte, 3=vieux)
   * à partir de l'âge et de la config VERMINE.AgeTypes.
   */
  _setAgeType() {
    const age = this.identity.age
    const ageTypes = CONFIG.VERMINE.AgeTypes
    const entries = Object.entries(ageTypes).reverse()
    for (const [type, cfg] of entries) {
      if (age >= parseInt(cfg.beginning, 10)) {
        this.identity.ageType = parseInt(type, 10)
        break
      }
    }
  }

  /**
   * Calcule le max de sang-froid :
   * somme des caractéristiques mentales + sociales + modificateur d'âge.
   * Un Fétiche équipé ajoute +1D ; une perte de Fétiche soustrait 1D.
   */
  _setSelfControlMax() {
    const abilities = Object.values(this.abilities)
    const modFromAge = this._getModFromAgeSelfControl()
    const sum = abilities
      .filter(a => a.category === "mental" || a.category === "social")
      .reduce((acc, a) => acc + a.value, 0)
    const bonus = this.experience?.reserveBonus?.self_control || 0
    const loss = this.experience?.feticheLoss?.self_control || 0
    const fetiche = VermineTraits.feticheItem(this.parent) ? 1 : 0
    this.attributes.self_control.max = Math.min(10, Math.max(0, sum + modFromAge + bonus + fetiche - loss))
  }

  /**
   * Calcule le max d'effort :
   * somme des caractéristiques physiques + manuelles + modificateur d'âge.
   * Un Fétiche équipé ajoute +1D ; une perte de Fétiche soustrait 1D.
   */
  _setEffortMax() {
    const abilities = Object.values(this.abilities)
    const modFromAge = this._getModFromAgeEffort()
    const sum = abilities
      .filter(a => a.category === "physical" || a.category === "manual")
      .reduce((acc, a) => acc + a.value, 0)
    const bonus = this.experience?.reserveBonus?.effort || 0
    const loss = this.experience?.feticheLoss?.effort || 0
    const fetiche = VermineTraits.feticheItem(this.parent) ? 1 : 0
    this.attributes.effort.max = Math.min(10, Math.max(0, sum + modFromAge + bonus + fetiche - loss))
  }

  /**
   * Calcule les seuils de blessures à partir de la Santé.
   */
  _setWoundThresholds() {
    const health = this.abilities.health.value
    const ageMods = this._getModFromAgeWounds()

    this.minorWound.threshold = health
    this.majorWound.threshold = health + 3
    this.deadlyWound.threshold = (health + 7 < 11) ? health + 7 : 10

    this.minorWound.max = 4 + ageMods.l
    this.majorWound.max = 3 + ageMods.h
    this.deadlyWound.max = 2 + ageMods.d
  }

  /**
   * Met à jour le label du statut de combat en fonction de la difficulté.
   */
  _updateCombatStatus() {
    const difficulty = parseInt(this.combatStatus.difficulty) || 9
    let newLabel = "Passif"
    switch (difficulty) {
      case 5: newLabel = "Offensif"; break
      case 7: newLabel = "Actif"; break
      case 9: newLabel = "Passif"; break
    }
    if (this.combatStatus.label !== newLabel) {
      this.combatStatus.label = newLabel
    }
  }

  // ── Modificateurs liés à l'âge ──────────────────────────────────────

  /** @returns {number} Modificateur de sang-froid selon l'âge. */
  _getModFromAgeSelfControl() {
    return this.identity.ageType === 1 ? -1 : 0
  }

  /** @returns {number} Modificateur d'effort selon l'âge. */
  _getModFromAgeEffort() {
    if (this.identity.ageType === 1) return -1
    if (this.identity.ageType === 3) return -2
    return 0
  }

  /** @returns {{l: number, h: number, d: number}} Modificateurs de blessures selon l'âge. */
  _getModFromAgeWounds() {
    if (this.identity.ageType === 1) return { l: 0, h: 0, d: -1 }
    if (this.identity.ageType === 3) return { l: -1, h: -1, d: -1 }
    return { l: 0, h: 0, d: 0 }
  }
}
