/**
 * DataModel pour les acteurs de type "community" (Communauté).
 * La Communauté est l'extension sédentarisée d'un Groupe : elle englobe le
 * Groupe de personnages, des Figures et des Habitants répartis en Compagnies.
 * Le socle couvre l'identité, la géographie, l'histoire, les objectifs, la
 * taille/l'effectif, les quatre Domaines (8 jauges), le Moral et les réserves.
 */
import {
  attributeSchema,
  levelSchema,
  combatStatusSchema
} from "./_shared.mjs"

export default class VermineCommunityData extends foundry.abstract.TypeDataModel {

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

  /** @override */
  static defineSchema() {
    const fields = foundry.data.fields
    const reqInt = { required: true, nullable: false, integer: true }
    const gauge = () => attributeSchema(0, 0, 10)

    return {
      // Statut de combat (base, peu utilisé pour une Communauté)
      combatStatus: combatStatusSchema("9"),

      // Identité
      identity: new fields.SchemaField({
        totem: new fields.StringField({ required: true, nullable: false, initial: "" }),
        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: "" }),
        instincts: new fields.StringField({ required: true, nullable: false, initial: "" }),
        prohibits: new fields.StringField({ required: true, nullable: false, initial: "" }),
        // Âge de la Communauté : recent | established | old
        age: new fields.StringField({ required: true, nullable: false, initial: "recent" }),
        notes: new fields.HTMLField({ required: true, initial: "", textSearch: true })
      }),

      // Géographie / localisation
      location: new fields.SchemaField({
        sector: new fields.StringField({ required: true, nullable: false, initial: "" }),
        placeType: new fields.StringField({ required: true, nullable: false, initial: "" }),
        landmarks: new fields.HTMLField({ required: true, initial: "", textSearch: true }),
        territory: new fields.HTMLField({ required: true, initial: "", textSearch: true })
      }),

      // Histoire
      history: new fields.SchemaField({
        founding: new fields.StringField({ required: true, nullable: false, initial: "" }),
        events: new fields.HTMLField({ required: true, initial: "", textSearch: true }),
        relations: new fields.HTMLField({ required: true, initial: "", textSearch: true })
      }),

      // Objectifs : un majeur + des mineurs
      objectives: new fields.SchemaField({
        major: new fields.StringField({ required: true, nullable: false, initial: "" }),
        minor: new fields.ArrayField(new fields.StringField({ required: true, nullable: false, initial: "" }))
      }),

      // Taille (1-3) et effectif
      size: attributeSchema(1, 1, 3),
      population: new fields.NumberField({ ...reqInt, initial: 0, min: 0 }),

      // Domaines : 4 Domaines × 2 sections (jauges en Dés)
      domains: new fields.SchemaField({
        resources: new fields.SchemaField({
          vivre: gauge(),
          supplies: gauge()
        }),
        security: new fields.SchemaField({
          defense: gauge(),
          care: gauge()
        }),
        dynamism: new fields.SchemaField({
          cohesion: gauge(),
          productivity: gauge()
        }),
        relations: new fields.SchemaField({
          human: gauge(),
          ecology: gauge()
        })
      }),

      // Moral (comme le Groupe) : value 0-7, level dérivé
      morale: new fields.SchemaField({
        level: new fields.StringField({ required: true, nullable: false, initial: "normal" }),
        value: new fields.NumberField({ ...reqInt, initial: 7, min: 0, max: 7 }),
        min: new fields.NumberField({ ...reqInt, initial: 0, min: 0 }),
        max: new fields.NumberField({ ...reqInt, initial: 7, min: 0 })
      }),

      // Réserve de Groupe
      reserve: attributeSchema(0, 0, 10),

      // Dés collectifs de la Communauté
      material: new fields.NumberField({ ...reqInt, initial: 0, min: 0 }),
      experience: new fields.SchemaField({
        dice: new fields.NumberField({ ...reqInt, initial: 0, min: 0 })
      }),

      // Niveau de la Communauté (pour l'expérience des habitants)
      level: levelSchema(1, 1, 10),

      // Groupe de personnages rattaché (id d'acteur)
      groupId: new fields.StringField({ required: true, nullable: false, initial: "" }),

      // Habitants (phase 2) : Figures et Compagnies
      figures: new fields.ArrayField(new fields.SchemaField({
        name: new fields.StringField({ required: true, nullable: false, initial: "" }),
        role: new fields.StringField({ required: true, nullable: false, initial: "" }),
        totem: new fields.StringField({ required: true, nullable: false, initial: "" }),
        specialty: new fields.SchemaField({
          name: new fields.StringField({ required: true, nullable: false, initial: "" }),
          score: new fields.NumberField({ ...reqInt, initial: 3, min: 0, max: 10 })
        })
      })),
      companies: new fields.ArrayField(new fields.SchemaField({
        name: new fields.StringField({ required: true, nullable: false, initial: "" }),
        specialty: new fields.SchemaField({
          name: new fields.StringField({ required: true, nullable: false, initial: "" }),
          score: new fields.NumberField({ ...reqInt, initial: 3, min: 0, max: 10 })
        }),
        level: levelSchema(1, 1, 4),
        members: new fields.NumberField({ ...reqInt, initial: 1, min: 0 }),
        figureName: new fields.StringField({ required: true, nullable: false, initial: "" })
      }))
    }
  }

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

    // 1. État (Crise/Bas/Stable/Opulent) de chaque jauge de Domaine
    this._computeGaugeStates()

    // 2. Les quatre Domaines sont-ils Bas ? (Moral inactif)
    this._computeAllDomainsLow()

    // 3. Mettre à jour le niveau de Moral selon la valeur
    this._updateMorale()
  }

  /**
   * État d'une jauge selon sa valeur en Dés.
   * Crise 0D / Bas 1-2D / Stable 3-5D / Opulent 6D+.
   * @param {number} value
   * @returns {string}
   */
  static gaugeState(value) {
    const v = parseInt(value, 10) || 0
    if (v >= 6) return "opulent"
    if (v >= 3) return "stable"
    if (v >= 1) return "low"
    return "crisis"
  }

  _computeGaugeStates() {
    for (const domain of Object.values(this.domains)) {
      for (const gauge of Object.values(domain)) {
        gauge.state = VermineCommunityData.gaugeState(gauge.value)
      }
    }
  }

  /**
   * Un Domaine est "Bas" lorsque ses deux sections sont à 2D ou moins.
   * Si les quatre Domaines sont Bas, le Bonus de Moral est inactif.
   */
  _computeAllDomainsLow() {
    const domainLow = (domain) => Object.values(domain).every(g => (parseInt(g.value, 10) || 0) <= 2)
    this.allDomainsLow = Object.values(this.domains).every(domainLow)
  }

  /**
   * Met à jour le niveau de Moral en fonction de la valeur de dés.
   * Règles : 7D = Haut, 6-3D = Normal, 2-1D = Bas, 0D = Crise.
   */
  _updateMorale() {
    const moraleValue = parseInt(this.morale?.value, 10) || 0
    if (this.morale.level && this.morale.level !== "normal") return
    if (moraleValue >= 7) {
      this.morale.level = "high"
    } else if (moraleValue >= 3) {
      this.morale.level = "normal"
    } else if (moraleValue >= 1) {
      this.morale.level = "low"
    } else {
      this.morale.level = "crisis"
    }
  }
}
