/**
 * DataModel pour les acteurs de type "creature" (créature).
 * Étend foundry.abstract.TypeDataModel.
 */
import {
  woundSchema,
  combatStatusSchema,
  equipmentSchema,
  attributeSchema
} from "./_shared.mjs"

export default class VermineCreatureData extends foundry.abstract.TypeDataModel {

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

  /** @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(),

      // Identité
      identity: new fields.SchemaField({
        profile: new fields.StringField({ required: true, nullable: false, initial: "" }),
        origin: new fields.StringField({ required: true, nullable: false, initial: "" }),
        theme: new fields.StringField({ required: true, nullable: false, initial: "" }),
        notes: new fields.HTMLField({ required: true, initial: "" }),
        biography: new fields.HTMLField({ required: true, initial: "" })
      }),

      // Compétences (description libre)
      skills: new fields.StringField({ required: true, nullable: false, initial: "" }),

      // Modes de jeu actifs
      modes: new fields.SchemaField({
        survival: new fields.BooleanField({ required: true, initial: true }),
        nightmare: new fields.BooleanField({ required: true, initial: true }),
        apocalypse: new fields.BooleanField({ required: true, initial: false })
      }),

      // Niveaux de créature (patron, taille, rôle, meute)
      pattern: attributeSchema(1, 1, 4),
      size: attributeSchema(0, 0, 3),
      role: attributeSchema(1, 1, 4),
      pack: attributeSchema(0, 0, 3),

      // Valeurs calculées (dérivées de pattern/size/role/pack)
      computed: new fields.SchemaField({
        attack: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
        damage: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
        vigor: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
        reaction: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
        reactionBonus: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
        pools: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
        gear: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 9 }),
        gearHindrance: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
        protection: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 1 })
      }),

      // Ajustements manuels des valeurs calculées : permettent les disparités
      // entre créatures de même Gabarit/Taille (ex. un sanglier avec une
      // Protection supérieure à celle d'un chien, un loup plus vigoureux).
      // Base dérivée + ajustement = valeur finale (jamais négative).
      adjustments: new fields.SchemaField({
        attack: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
        damage: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
        vigor: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
        reaction: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
        reactionBonus: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
        pools: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
        gear: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
        gearHindrance: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }),
        protection: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 })
      }),

      // Équipement
      equipment: equipmentSchema()
    }
  }

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

    // 1. Calculer les valeurs dérivées (attaque, dégâts, vigueur, etc.)
    this._calculateCreatureComputedValues()

    // 2. Calculer les seuils de blessures
    this._calculateCreatureWoundThresholds()

    // 3. Mettre à jour le statut de combat
    this._updateCombatStatus()
  }

  /**
   * Calcule les valeurs dérivées à partir des niveaux de patron, taille, rôle et meute.
   * Utilise les configs CONFIG.VERMINE.creaturePatternLevels, .creatureSizeLevels,
   * .creatureRoleLevels, .creaturePackLevels.
   *
   * Règles :
   * - Attaque = pattern.attack + size.attack + pack.attack
   * - Dégâts  = pattern.damage + size.vigor + pack.damage
   * - Vigueur = size.vigor + pack.damage
   * - Réaction = role.reaction + role.reaction_bonus
   */
  _calculateCreatureComputedValues() {
    const patternLevel = this.pattern?.value || 1
    const sizeLevel = this.size?.value || 0
    const roleLevel = this.role?.value || 1
    const packLevel = this.pack?.value || 0

    const patternConfig = CONFIG.VERMINE.creaturePatternLevels[patternLevel] || {}
    const roleConfig = CONFIG.VERMINE.creatureRoleLevels[roleLevel] || {}
    const packConfig = CONFIG.VERMINE.creaturePackLevels[packLevel] || {}

    // Les modificateurs de Taille se cumulent : une créature de Taille N applique
    // les modificateurs de chaque Taille de 1 à N (Taille 0 = insecte, aucun).
    const sizeLevels = CONFIG.VERMINE.creatureSizeLevels || {}
    let sizeAttack = 0
    let sizeVigor = 0
    for (let i = 1; i <= sizeLevel; i++) {
      const cfg = sizeLevels[i] || {}
      sizeAttack += cfg.attack || 0
      sizeVigor += cfg.vigor || 0
    }

    // Attaque : patron + taille + meute.
    // NB : le Rôle ne donne que la Réaction (dés + réussites automatiques),
    // il n'ajoute pas de dés d'attaque (regles_creatures.txt).
    this.computed.attack = (patternConfig.attack || 0)
      + sizeAttack
      + (packConfig.attack || 0)

    // Dégâts : patron + vigueur de taille + meute
    this.computed.damage = (patternConfig.damage || 0)
      + sizeVigor
      + (packConfig.damage || 0)

    // Vigueur : taille + meute
    this.computed.vigor = sizeVigor + (packConfig.damage || 0)

    // Réaction : rôle (le bonus de rôle est compté séparément et ajouté
    // comme réussites automatiques par le NpcRollDialog — cf. modèle PNJ).
    this.computed.reaction = roleConfig.reaction || 0
    this.computed.reactionBonus = roleConfig.reaction_bonus || 0

    // Réserves
    this.computed.pools = roleConfig.pools || 0

    // Équipement et handicap
    this.computed.gear = roleConfig.gear || 9
    this.computed.gearHindrance = roleConfig.gear_hindrance || 0

    // Protection
    this.computed.protection = roleConfig.protection || 1

    // Ajustements manuels (base + modificateur), plancher à 0.
    const adj = this.adjustments ?? {}
    this.computed.attack = Math.max(0, this.computed.attack + (adj.attack ?? 0))
    this.computed.damage = Math.max(0, this.computed.damage + (adj.damage ?? 0))
    this.computed.vigor = Math.max(0, this.computed.vigor + (adj.vigor ?? 0))
    this.computed.reaction = Math.max(0, this.computed.reaction + (adj.reaction ?? 0))
    this.computed.reactionBonus = Math.max(0, this.computed.reactionBonus + (adj.reactionBonus ?? 0))
    this.computed.pools = Math.max(0, this.computed.pools + (adj.pools ?? 0))
    this.computed.gear = Math.max(0, this.computed.gear + (adj.gear ?? 0))
    this.computed.gearHindrance = Math.max(0, this.computed.gearHindrance + (adj.gearHindrance ?? 0))
    this.computed.protection = Math.max(0, this.computed.protection + (adj.protection ?? 0))
  }

  /**
   * Calcule les seuils et les cercles de blessures à partir du patron, de la
   * taille et de la meute.
   *
   * Règles (regles_creatures.txt) :
   * - Seuil = contribution du Gabarit + contributions de Taille (cumulées).
   *   Le Groupe n'ajoute PAS de seuil (tableau « Groupe » : cercles seuls).
   * - Cercles = cercles du Gabarit + cercles de Taille (cumulés) + cercles du Groupe.
   */
  _calculateCreatureWoundThresholds() {
    const patternLevel = this.pattern?.value || 1
    const sizeLevel = this.size?.value || 0
    const packLevel = this.pack?.value || 0

    const patternConfig = CONFIG.VERMINE.creaturePatternLevels[patternLevel] || {}
    const packConfig = CONFIG.VERMINE.creaturePackLevels[packLevel] || {}

    // Les modificateurs de Taille se cumulent (Taille N = somme des tailles 1..N).
    const sizeLevels = CONFIG.VERMINE.creatureSizeLevels || {}
    const sizeThresholds = { minor: 0, major: 0, deadly: 0 }
    const sizeWounds = { minor: 0, major: 0, deadly: 0 }
    for (let i = 1; i <= sizeLevel; i++) {
      const cfg = sizeLevels[i] || {}
      sizeThresholds.minor += cfg.minorThreshold || 0
      sizeThresholds.major += cfg.majorThreshold || 0
      sizeThresholds.deadly += cfg.deadlyThreshold || 0
      sizeWounds.minor += cfg.minorWound || 0
      sizeWounds.major += cfg.majorWound || 0
      sizeWounds.deadly += cfg.deadlyWound || 0
    }

    // Seuils : gabarit + taille cumulée (pas de contribution du groupe).
    this.minorWound.threshold = (patternConfig.minorThreshold ?? 0) + sizeThresholds.minor
    this.majorWound.threshold = (patternConfig.majorThreshold ?? 0) + sizeThresholds.major
    this.deadlyWound.threshold = (patternConfig.deadlyThreshold ?? 0) + sizeThresholds.deadly

    // Cercles : gabarit + taille cumulée + groupe.
    this.minorWound.max = (patternConfig.minorWound ?? 0) + sizeWounds.minor + (packConfig.minorWound ?? 0)
    this.majorWound.max = (patternConfig.majorWound ?? 0) + sizeWounds.major + (packConfig.majorWound ?? 0)
    this.deadlyWound.max = (patternConfig.deadlyWound ?? 0) + sizeWounds.deadly + (packConfig.deadlyWound ?? 0)
  }

  /**
   * 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
    }
  }
}
