import { SYSTEM } from "../config/system.mjs"

export default class CelestopolCharacter extends foundry.abstract.TypeDataModel {
  static defineSchema() {
    const fields = foundry.data.fields
    const reqInt = { required: true, nullable: false, integer: true }
    const schema = {}

    // Concept du personnage
    schema.concept  = new fields.StringField({ required: true, nullable: false, initial: "" })
    schema.metier   = new fields.StringField({ required: true, nullable: false, initial: "" })
    schema.faction  = new fields.StringField({ required: true, nullable: false, initial: "" })

    // Initiative (calculée mais stockée pour affichage)
    schema.initiative = new fields.NumberField({ ...reqInt, initial: 0, min: 0 })

    // Anomalie du personnage
    schema.anomaly = new fields.SchemaField({
      type:  new fields.StringField({ required: true, nullable: false, initial: "none",
               choices: Object.keys(SYSTEM.ANOMALY_TYPES) }),
      value: new fields.NumberField({ ...reqInt, initial: 0, min: 0, max: 8 }),
    })

    // Les 4 stats avec leurs domaines
    const skillField = (label) => new fields.SchemaField({
      label: new fields.StringField({ required: true, initial: label }),
      value: new fields.NumberField({ ...reqInt, initial: 0, min: 0, max: 8 }),
      level1: new fields.BooleanField({ required: true, initial: false }),
      level2: new fields.BooleanField({ required: true, initial: false }),
      level3: new fields.BooleanField({ required: true, initial: false }),
      level4: new fields.BooleanField({ required: true, initial: false }),
      level5: new fields.BooleanField({ required: true, initial: false }),
      level6: new fields.BooleanField({ required: true, initial: false }),
      level7: new fields.BooleanField({ required: true, initial: false }),
      level8: new fields.BooleanField({ required: true, initial: false }),
    })

    const statField = (statId) => {
      const skills = SYSTEM.SKILLS[statId]
      const skillSchema = {}
      for (const [key, skill] of Object.entries(skills)) {
        skillSchema[key] = skillField(skill.label)
      }
      return new fields.SchemaField({
        label:  new fields.StringField({ required: true, initial: SYSTEM.STATS[statId].label }),
        res:    new fields.NumberField({ ...reqInt, initial: 0, min: 0, max: 8 }),
        ...skillSchema,
      })
    }

    schema.stats = new fields.SchemaField({
      ame:    statField("ame"),
      corps:  statField("corps"),
      coeur:  statField("coeur"),
      esprit: statField("esprit"),
    })

    // Blessures (8 cases)
    const woundField = (idx) => new fields.SchemaField({
      checked: new fields.BooleanField({ required: true, initial: false }),
      malus:   new fields.NumberField({ ...reqInt, initial: SYSTEM.WOUND_LEVELS[idx]?.malus ?? 0 }),
    })
    schema.blessures = new fields.SchemaField({
      lvl: new fields.NumberField({ ...reqInt, initial: 0, min: 0, max: 8 }),
      b1:  woundField(1), b2: woundField(2), b3: woundField(3), b4: woundField(4),
      b5:  woundField(5), b6: woundField(6), b7: woundField(7), b8: woundField(8),
    })

    // Destin (8 cases)
    const destField = () => new fields.SchemaField({
      checked: new fields.BooleanField({ required: true, initial: false }),
    })
    schema.destin = new fields.SchemaField({
      lvl: new fields.NumberField({ ...reqInt, initial: 0, min: 0, max: 8 }),
      d1: destField(), d2: destField(), d3: destField(), d4: destField(),
      d5: destField(), d6: destField(), d7: destField(), d8: destField(),
    })

    // Spleen (8 cases)
    schema.spleen = new fields.SchemaField({
      lvl: new fields.NumberField({ ...reqInt, initial: 0, min: 0, max: 8 }),
      s1: destField(), s2: destField(), s3: destField(), s4: destField(),
      s5: destField(), s6: destField(), s7: destField(), s8: destField(),
    })

    // Attributs de personnage (Entregent, Fortune, Rêve, Vision)
    const persoAttrField = () => new fields.SchemaField({
      value: new fields.NumberField({ ...reqInt, initial: 0, min: 0 }),
      max:   new fields.NumberField({ ...reqInt, initial: 0, min: 0 }),
    })
    schema.attributs = new fields.SchemaField({
      entregent: persoAttrField(),
      fortune:   persoAttrField(),
      reve:      persoAttrField(),
      vision:    persoAttrField(),
    })

    // Factions - 9 checkboxes per faction (like wound tracks)
    const factionField = () => new fields.SchemaField({
      value: new fields.NumberField({ ...reqInt, initial: 0 }),
      level1: new fields.BooleanField({ required: true, initial: false }),
      level2: new fields.BooleanField({ required: true, initial: false }),
      level3: new fields.BooleanField({ required: true, initial: false }),
      level4: new fields.BooleanField({ required: true, initial: false }),
      level5: new fields.BooleanField({ required: true, initial: false }),
      level6: new fields.BooleanField({ required: true, initial: false }),
      level7: new fields.BooleanField({ required: true, initial: false }),
      level8: new fields.BooleanField({ required: true, initial: false }),
      level9: new fields.BooleanField({ required: true, initial: false }),
    })
    schema.factions = new fields.SchemaField({
      pinkerton:    factionField(),
      police:       factionField(),
      okhrana:      factionField(),
      lunanovatek:  factionField(),
      oto:          factionField(),
      syndicats:    factionField(),
      vorovskoymir: factionField(),
      cour:         factionField(),
      perso1: new fields.SchemaField({
        label: new fields.StringField({ required: true, nullable: false, initial: "" }),
        value: new fields.NumberField({ ...reqInt, initial: 0 }),
      }),
      perso2: new fields.SchemaField({
        label: new fields.StringField({ required: true, nullable: false, initial: "" }),
        value: new fields.NumberField({ ...reqInt, initial: 0 }),
      }),
    })

    // Préférences de jet (mémorisé entre sessions)
    schema.prefs = new fields.SchemaField({
      rollMoonDie: new fields.BooleanField({ required: true, initial: false }),
      difficulty:  new fields.StringField({ required: true, nullable: false, initial: "normal" }),
    })

    // Description & notes
    schema.description = new fields.HTMLField({ required: true, textSearch: true })
    schema.notes       = new fields.HTMLField({ required: true, textSearch: true })

    // Données biographiques
    schema.biodata = new fields.SchemaField({
      age:       new fields.StringField({ required: true, nullable: false, initial: "" }),
      genre:     new fields.StringField({ required: true, nullable: false, initial: "" }),
      taille:    new fields.StringField({ required: true, nullable: false, initial: "" }),
      yeux:      new fields.StringField({ required: true, nullable: false, initial: "" }),
      naissance: new fields.StringField({ required: true, nullable: false, initial: "" }),
      cheveux:   new fields.StringField({ required: true, nullable: false, initial: "" }),
      origine:   new fields.StringField({ required: true, nullable: false, initial: "" }),
    })

    return schema
  }

  static LOCALIZATION_PREFIXES = ["CELESTOPOL.Character"]

  prepareDerivedData() {
    super.prepareDerivedData()

    // Calcul automatique de la valeur de chaque domaine = nombre de cases cochées
    for (const stat of Object.values(this.stats)) {
      for (const skill of Object.values(stat)) {
        if (typeof skill !== "object" || !("level1" in skill)) continue
        skill.value = [1,2,3,4,5,6,7,8].filter(i => skill[`level${i}`]).length
      }
    }

    // Calcul automatique de la valeur de chaque faction = nombre de cases cochées
    for (const faction of Object.values(this.factions)) {
      if (typeof faction !== "object" || !("level1" in faction)) continue
      faction.value = [1,2,3,4,5,6,7,8,9].filter(i => faction[`level${i}`]).length
    }

    // Initiative PJ : 4 + Mobilité (Corps) + Inspiration (Cœur)  [après calcul des domaines]
    this.initiative = 4 + (this.stats.corps.mobilite?.value ?? 0) + (this.stats.coeur.inspiration?.value ?? 0)
  }

  /**
   * Calcule le malus de blessures actif.
   * @returns {number}
   */
  getWoundMalus() {
    const lvl = Math.max(0, Math.min(8, this.blessures.lvl))
    return SYSTEM.WOUND_LEVELS[lvl]?.malus ?? 0
  }

  /**
   * Lance les dés pour un domaine donné.
   * @param {string} statId   - Id de la stat (ame, corps, coeur, esprit)
   * @param {string} skillId  - Id du domaine
   */
  async roll(statId, skillId) {
    const { CelestopolRoll } = await import("../documents/roll.mjs")
    const skill = this.stats[statId][skillId]
    if (!skill) return null

    return CelestopolRoll.prompt({
      actorId:       this.parent.id,
      actorName:     this.parent.name,
      actorImage:    this.parent.img,
      statId,
      skillId,
      statLabel:     SYSTEM.STATS[statId]?.label,
      skillLabel:    skill.label,
      skillValue:    skill.value,
      woundMalus:    this.getWoundMalus(),
      woundLevel:    this.blessures.lvl,
      difficulty:    this.prefs.difficulty,
      rollMoonDie:   this.prefs.rollMoonDie ?? false,
      destGaugeFull: this.destin.lvl >= 8,
    })
  }
}
