/* -------------------------------------------- */
import { MournbladeUtility } from "./mournblade-utility.js";
import { MournbladeRollDialog } from "./applications/mournblade-roll-dialog.mjs";
import MournbladeInvocationDialog from "./applications/mournblade-invocation-dialog.mjs";
import MournbladeInvocationDemonDialog from "./applications/mournblade-invocation-demon-dialog.mjs";
import MournbladeInvocationEspritDialog from "./applications/mournblade-invocation-esprit-dialog.mjs";
import MournbladeEnchantementDialog from "./applications/mournblade-enchantement-dialog.mjs";

/* -------------------------------------------- */
const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10]
const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8]

/* -------------------------------------------- */
/**
 * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system.
 * @extends {Actor}
 */
export class MournbladeActor extends Actor {
  prepareData() {
    super.prepareData();

    // Calculate derived attributes
    const data = this.system;

    if (this.type == 'personnage') {
      // Compute base health and max soul from attributes (derived, no DB write needed)
      data.sante.base = data.sante.bonus + (data.attributs.pui.value + data.attributs.tre.value) * 2 + 5;
      data.ame.fullmax = (data.attributs.cla.value + data.attributs.tre.value) * data.biodata.amemultiplier + 5;
    }

    // Calculate total health
    data.sante.total = data.sante.base + data.sante.bonus;

    // Calculate current health
    data.sante.current = data.sante.total - data.sante.nonletaux - data.sante.letaux;

    // Calculate total ame
    data.ame.total = data.ame.fullmax;

    // Calculate balance
    data.balance.total = data.balance.loi + data.balance.chaos;
  }

  prepareDerivedData() {
    super.prepareDerivedData();
  }

  /* -------------------------------------------- */
  /**
   * Override the create() function to provide additional SoS functionality.
   *
   * This overrided create() function adds initial items
   * Namely: Basic skills, money,
   *
   * @param {Object} data        Barebones actor data which this function adds onto.
   * @param {Object} options     (Unused) Additional options which customize the creation workflow.
   *
   */

  static async create(data, options) {

    // Case of compendium global import
    if (data instanceof Array) {
      return super.create(data, options);
    }
    // If the created actor has items (only applicable to foundry.utils.duplicated actors) bypass the new actor creation logic
    if (data.items) {
      let actor = super.create(data, options);
      return actor;
    }

    if (data.type == 'personnage') {
      const skills = await MournbladeUtility.loadCompendium("fvtt-mournblade.skills")
      data.items = skills.map(i => i.toObject())
    }
    if (data.type == 'creature') {
      const skills = await MournbladeUtility.loadCompendium("fvtt-mournblade.skills-creatures")
      data.items = skills.map(i => i.toObject())
      data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-mournblade/assets/icons/arme.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } })
      data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-mournblade/assets/icons/arme.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } })
    }


    return super.create(data, options);
  }

  /* -------------------------------------------- */
  setModifier(name, type, value) {
    this.createEmbeddedDocuments("Item", [{ type: "modifier", name: name, system: { modifiertype: type, value: value } }])
    ui.notifications.info("Le modificateur " + name + " a été ajouté à " + this.name + ".")
  }

  /* -------------------------------------------- */
  prepareArme(arme) {
    arme = foundry.utils.duplicate(arme)
    let combat = this.getCombatValues()
    const enchBonus = (arme.system.enchantementLoi?.actif && arme.system.enchantementLoi?.bonus > 0)
      ? arme.system.enchantementLoi.bonus : 0
    if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") {
      arme.system.isMelee = true
      let competence = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")
      if (competence) {
        arme.system.competence = foundry.utils.duplicate(competence)
        arme.system.attrKey = "pui"
        arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal
        arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + combat.attaqueModifier + enchBonus
        if (arme.system.isdefense) {
          arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.bonusmaniementdef
        }
      } else {
        arme.system.competence = null
        arme.system.totalOffensif = 0
        arme.system.totalDegats = arme.system.degats
        arme.system.totalDefensif = 0
      }
    }
    if (arme.system.typearme == "jet" || arme.system.typearme == "tir") {
      arme.system.isDistance = true
      let competence = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance")
      if (competence) {
        arme.system.competence = foundry.utils.duplicate(competence)
        arme.system.attrKey = "adr"
        arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + combat.attaqueModifier + enchBonus
        arme.system.totalDegats = arme.system.degats
        if (arme.system.isdefense) {
          arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.bonusmaniementdef
        }
      } else {
        arme.system.competence = null
        arme.system.totalOffensif = 0
        arme.system.totalDegats = arme.system.degats
        arme.system.totalDefensif = 0
      }
    }
    return arme
  }
  /* -------------------------------------------- */
  prepareBouclier(bouclier) {
    bouclier = foundry.utils.duplicate(bouclier)
    let combat = this.getCombatValues()
    const enchBonus = (bouclier.system.enchantementLoi?.actif && bouclier.system.enchantementLoi?.bonus > 0)
      ? bouclier.system.enchantementLoi.bonus : 0
    let competence = this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée")
    if (competence) {
      bouclier.system.competence = foundry.utils.duplicate(competence)
      bouclier.system.attrKey = "pui"
      bouclier.system.totalDegats = bouclier.system.degats + "+" + combat.bonusDegatsTotal
      bouclier.system.totalOffensif = this.system.attributs.pui.value + bouclier.system.competence.system.niveau + enchBonus
      bouclier.system.isdefense = true
      bouclier.system.bonusmaniementoff = 0
      bouclier.system.totalDefensif = combat.defenseTotal + bouclier.system.competence.system.niveau + bouclier.system.bonusdefense
    } else {
      bouclier.system.competence = null
      bouclier.system.totalOffensif = 0
      bouclier.system.totalDegats = bouclier.system.degats
      bouclier.system.totalDefensif = 0
    }
    return bouclier
  }

  /* -------------------------------------------- */
  getWeapons() {
    let armes = []
    for (let arme of this.items) {
      if (arme.type == "arme") {
        armes.push(this.prepareArme(arme))
      }
      if (arme.type == "bouclier") {
        armes.push(this.prepareBouclier(arme))
      }
    }
    MournbladeUtility.sortArrayObjectsByName(armes)
    return armes
  }

  /* -------------------------------------------- */
  getModifiersForRoll() {
    let modifiers = []
    for (let mod of this.items) {
      if (mod.type == "modifier" && mod.system.modifiertype == "roll") {
        let modObj = mod.toObject()
        modObj.system.apply = true
        modifiers.push(modObj)
      }
    }
    MournbladeUtility.sortArrayObjectsByName(modifiers)
    return modifiers
  }

  /* -------------------------------------------- */
  getItemSorted(types) {
    let items = this.items.filter(item => types.includes(item.type)) || []
    MournbladeUtility.sortArrayObjectsByName(items)
    return items
  }
  getDons() {
    return this.getItemSorted(["don"])
  }
  getPactes() {
    return this.getItemSorted(["pacte"])
  }
  getTendances() {
    return this.getItemSorted(["tendance"])
  }
  getRunes() {
    return this.getItemSorted(["rune"])
  }
  getEquipments() {
    return this.getItemSorted(["equipement"])
  }
  getModifiers() {
    return this.getItemSorted(["modifier"])
  }
  getTraitsChaotiques() {
    return this.getItemSorted(["traitchaotique"])
  }
  getTraitsEspeces() {
    return this.getItemSorted(["traitespece"])
  }
  getMonnaies() {
    return this.getItemSorted(["monnaie"])
  }
  getPotions() {
    return this.getItemSorted(["potion"])
  }
  getArmors() {
    return this.getItemSorted(["protection"])
  }
  getCapacites() {
    return this.getItemSorted(["capacite"])
  }
  getRuneEffects() {
    return this.getItemSorted(["runeeffect"])
  }
  getOrigine() {
    return this.items.find(item => item.type == "origine")
  }
  getMetier() {
    return this.items.find(item => item.type == "metier")
  }
  getHeritage() {
    return this.items.find(item => item.type == "heritage")
  }
  /* -------------------------------------------- */
  getSkills() {
    let comp = []
    for (let item of this.items) {
      item = foundry.utils.duplicate(item)
      if (item.type == "competence") {
        item.system.attribut1total = item.system.niveau + (this.system.attributs[item.system.attribut1]?.value || 0)
        item.system.attribut2total = item.system.niveau + (this.system.attributs[item.system.attribut2]?.value || 0)
        item.system.attribut3total = item.system.niveau + (this.system.attributs[item.system.attribut3]?.value || 0)
        if (item.system.niveau == 0) {
          item.system.attribut1total -= 3
          item.system.attribut2total -= 3
          item.system.attribut3total -= 3
        }
        item.system.attribut1label = this.system.attributs[item.system.attribut1]?.label || ""
        item.system.attribut2label = this.system.attributs[item.system.attribut2]?.label || ""
        item.system.attribut3label = this.system.attributs[item.system.attribut3]?.label || ""
        comp.push(item)
      }
    }
    MournbladeUtility.sortArrayObjectsByName(comp)
    return comp
  }

  /* -------------------------------------------- */
  getProtectionTotal() {
    let protection = 0
    for (let item of this.items) {
      if (item.type == "protection" && item.system.equipped) {
        protection += item.system.protection
      }
    }
    return protection
  }

  /* -------------------------------------------- */
  getAspect() {
    return (this.system.balance.loi > this.system.balance.chaos) ? this.system.balance.loi : this.system.balance.chaos
  }
  getMarge() {
    return Math.abs(this.system.balance.loi - this.system.balance.chaos)
  }
  getAlignement() {
    return (this.system.balance.loi > this.system.balance.chaos) ? "loyal" : "chaotique"
  }

  /* -------------------------------------------- */
  getDefenseBase() {
    return this.system.attributs.tre.value + 5
  }

  /* -------------------------------------------- */
  getVitesseBase() {
    return 5 + __vitesseBonus[Math.min(21, Math.max(0, this.system.attributs.adr.value))]
  }

  /* -------------------------------------------- */
  getCombatValues() {
    let defenserModifier = 0
    this.items.filter(item => item.type == "modifier" && item.system.modifiertype == "defense").map(e => defenserModifier += e.system.value)
    let attaqueModifier = 0
    this.items.filter(item => item.type == "modifier" && item.system.modifiertype == "attaque").map(e => attaqueModifier += e.system.value)

    let combat = {
      defenserModifier,
      attaqueModifier,
      initBase: this.system.attributs.adr.value,
      initTotal: this.system.attributs.adr.value + this.system.combat.initbonus,
      bonusDegats: this.getBonusDegats(),
      bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats,
      vitesseBase: this.getVitesseBase(),
      vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus,
      defenseBase: this.getDefenseBase(),
      defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + defenserModifier
    }
    return combat
  }

  /* -------------------------------------------- */
  _preUpdate(changed, options, user) {

    super._preUpdate(changed, options, user);
  }

  /* -------------------------------------------- */
  getItemById(id) {
    let item = this.items.find(item => item.id == id);
    if (item) {
      item = foundry.utils.duplicate(item)
    }
    return item;
  }

  /* -------------------------------------------- */
  async equipItem(itemId) {
    let item = this.items.find(item => item.id == itemId)
    if (item?.system) {
      let update = { _id: item.id, "system.equipped": !item.system.equipped }
      await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity
    }
  }

  /* -------------------------------------------- */
  getStatusMalus() {
    if (this.system.biodata.ignoresantemalus) {
      return 0
    }

    let malusL = 0
    let malusNL = 0
    if (this.system.sante.base - this.system.sante.letaux < 10) {
      malusL = -2
    }
    if (this.system.sante.base - this.system.sante.letaux < 5) {
      malusL = -5
    }
    if (this.system.sante.base - this.system.sante.nonletaux < 10) {
      malusNL = -2
    }
    if (this.system.sante.base - this.system.sante.nonletaux < 5) {
      malusNL = -5
    }
    return Math.min(malusL, malusNL)
  }
  /* -------------------------------------------- */
  getAmeMalus() {
    if (this.system.biodata.ignoreamemalus) {
      return 0
    }
    let malusA = 0
    if (this.system.ame.currentmax - this.system.ame.value < 10) {
      malusA = -2
    }
    if (this.system.ame.currentmax - this.system.ame.value < 5) {
      malusA = -5
    }
    return malusA
  }

  /* -------------------------------------------- */
  editItemField(itemId, itemType, itemField, dataType, value) {
    let item = this.items.find(item => item.id == itemId)
    if (item) {
      console.log("Item ", item, itemField, dataType, value)
      if (dataType.toLowerCase() == "number") {
        value = Number(value)
      } else {
        value = String(value)
      }
      let update = { _id: item.id, [`system.${itemField}`]: value };
      this.updateEmbeddedDocuments("Item", [update])
    }
  }

  /* -------------------------------------------- */
  async incDecSante(type, value, applyArmure = true) {
    value = Number(value)
    if (value && applyArmure) {
      let protection = this.getProtectionTotal()
      value -= protection
      value = Math.max(0, Number(value))
    }
    if (value) {
      let newSante = foundry.utils.duplicate(this.system.sante)
      newSante[type] += Number(value)
      newSante[type] = Math.max(0, newSante[type])
      if (newSante[type] > this.system.sante.base) {
        value -= this.system.sante.base - newSante[type]
        newSante[type] = this.system.sante.base
      } else {
        value = 0
      }
      newSante[type] = Math.min(newSante[type], newSante.base)
      if (value && type == "nonletaux") {
        newSante["letaux"] += value
      }
      await this.update({ 'system.sante': newSante })
    }
  }

  /* -------------------------------------------- */
  async incDecAme(value) {
    value = Number(value)
    if (value) {
      let newAme = foundry.utils.duplicate(this.system.ame)
      newAme.value += Number(value)
      newAme.value = Math.max(0, newAme.value)
      newAme.value = Math.min(newAme.value, newAme.currentmax)
      await this.update({ 'system.ame': newAme })
    }
  }

  /* -------------------------------------------- */
  getBonneAventure() {
    return this.system.bonneaventure.actuelle
  }

  /* -------------------------------------------- */
  async changeBonneAventure(value) {
    let newBA = this.system.bonneaventure.actuelle
    newBA += value
    await this.update({ 'system.bonneaventure.actuelle': newBA })
  }

  /* -------------------------------------------- */
  getEclat() {
    return this.system.eclat.value
  }

  /* -------------------------------------------- */
  async changeEclat(value) {
    let newE = this.system.eclat.value
    newE += value
    await this.update({ 'system.eclat.value': newE })
  }

  /* -------------------------------------------- */
  canEclatDoubleD20() {
    return (this.getAlignement() == "loyal" && this.system.eclat.value > 0)
  }
  /* -------------------------------------------- */
  subPointsAme(runeMode, value) {
    let ame = foundry.utils.duplicate(this.system.ame)
    if (runeMode == "prononcer") {
      ame.value += value
    } else {
      ame.currentmax -= value
    }
    return this.update({ 'system.ame': ame })
  }

  /* -------------------------------------------- */
  compareName(a, b) {
    if (a.name < b.name) {
      return -1;
    }
    if (a.name > b.name) {
      return 1;
    }
    return 0;
  }

  /* -------------------------------------------- */
  getAttribute(attrKey) {
    return this.system.attributs[attrKey]
  }

  /* -------------------------------------------- */
  getBonusDegats() {
    if (this.type == "creature") {
      return 0
    }
    return __degatsBonus[Math.min(21, Math.max(0, this.system.attributs.pui.value))]
  }

  /* -------------------------------------------- */
  async equipGear(equipmentId) {
    let item = this.items.find(item => item.id == equipmentId);
    if (item && item.system.data) {
      let update = { _id: item.id, "system.equipped": !item.system.equipped };
      await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity
    }
  }

  /* -------------------------------------------- */
  getSubActors() {
    let subActors = [];
    for (let id of this.system.subactors) {
      subActors.push(foundry.utils.duplicate(game.actors.get(id)));
    }
    return subActors;
  }
  /* -------------------------------------------- */
  async addSubActor(subActorId) {
    let subActors = foundry.utils.duplicate(this.system.subactors);
    subActors.push(subActorId);
    await this.update({ 'system.subactors': subActors });
  }
  /* -------------------------------------------- */
  async delSubActor(subActorId) {
    let newArray = [];
    for (let id of this.system.subactors) {
      if (id != subActorId) {
        newArray.push(id);
      }
    }
    await this.update({ 'system.subactors': newArray });
  }

  /* -------------------------------------------- */
  async incDecQuantity(objetId, incDec = 0) {
    let objetQ = this.items.get(objetId)
    if (objetQ) {
      let newQ = objetQ.system.quantite + incDec;
      const updated = await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity
    }
  }
  /* -------------------------------------------- */
  getCompetence(compId) {
    return this.items.get(compId)
  }

  /* -------------------------------------------- */
  async setPredilectionUsed(compId, predIdx) {
    let comp = this.items.get(compId)
    let pred = foundry.utils.duplicate(comp.system.predilections)
    pred[predIdx].used = true
    await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }])
  }

  /* -------------------------------------------- */
  getInitiativeScore() {
    return Number(this.system.attributs.adr.value) + Number(this.system.combat.initbonus)
  }
  /* -------------------------------------------- */
  getBestDefenseValue() {
    let defenseList = this.items.filter(item => (item.type == "arme" || item.type == "bouclier") && item.system.equipped)
    let maxDef = 0
    let bestArme
    for (let arme of defenseList) {
      if (arme.type == "arme" && arme.system.isdefense) {
        arme = this.prepareArme(arme)
      }
      if (arme.type == "bouclier") {
        arme = this.prepareBouclier(arme)
      }
      if (arme.system.totalDefensif > maxDef) {
        maxDef = arme.system.totalDefensif
        bestArme = foundry.utils.duplicate(arme)
      }
    }
    return bestArme
  }
  /* -------------------------------------------- */
  depenseRessources(arme) {
    if (arme.system.nbressources && Number(arme.system.nbressources) > 0) {
      if (this.type == "creature") {
        let ressources = foundry.utils.duplicate(this.system.ressources)
        if (Number(ressources.value) >= Number(arme.system.nbressources)) {
          ressources.value -= arme.system.nbressources
          this.update({ 'system.ressources': ressources })
          ChatMessage.create({
            content: "L'utilisation de la capacité/arme a dépensé " + arme.system.nbressources + " ressources.",
            whisper: game.user.id,
            user: game.user.id
          });
        } else {
          ui.notifications.warn("Points de ressources insuffisants.")
        }
      } else {
        ui.notifications.warn("Les ressources ne sont pas disponibles pour les personnages.")
      }
    }
  }

  /* -------------------------------------------- */
  getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) {
    let rollData = MournbladeUtility.getBasicRollData()
    rollData.alias = this.name
    rollData.actorImg = this.img
    rollData.actorId = this.id
    rollData.tokenId = this.token?.id
    rollData.img = this.img
    rollData.canEclatDoubleD20 = this.canEclatDoubleD20()
    rollData.doubleD20 = false
    rollData.attributs = MournbladeUtility.getAttributs()
    rollData.selectDifficulte = true
    rollData.malusSante = this.getStatusMalus() + this.system.sante.malusmanuel
    rollData.malusAme = this.getAmeMalus()
    rollData.modifiers = this.getModifiersForRoll()
    rollData.desavantages = {}
    rollData.isMonte = this.system.combat.monte
    if (rollData.isMonte) {
      rollData.config.attaques["chargecavalerie"] = "Charge de cavalerie"
    }

    if (attrKey) {
      rollData.attrKey = attrKey
      if (attrKey != "tochoose") {
        rollData.actionImg = "systems/fvtt-mournblade/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp"
        rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey])
      }
    }
    if (compId) {
      rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {})
      rollData.actionImg = rollData.competence?.img
    }
    if (compName) {
      rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {})
      rollData.actionImg = rollData.competence?.img
    }
    return rollData
  }

  /* -------------------------------------------- */
  async rollAttribut(attrKey) {
    let rollData = this.getCommonRollData(attrKey)
    await MournbladeRollDialog.create(this, rollData)
  }

  /* -------------------------------------------- */
  async rollCompetence(attrKey, compId) {
    let rollData = this.getCommonRollData(attrKey, compId)
    console.log("RollDatra", rollData)
    await MournbladeRollDialog.create(this, rollData)
  }

  /* -------------------------------------------- */
  async rollRune(runeId) {
    let comp = this.items.find(comp => comp.type == "competence" && comp.name.toLowerCase() == "savoir : runes")
    if (!comp) {
      ui.notifications.warn("La compétence Savoirs : Runes n'a pas été trouvée, abandon.")
      return
    }
    let rollData = this.getCommonRollData("cla", undefined, "Savoir : Runes")
    rollData.rune = foundry.utils.duplicate(this.items.get(runeId) || {})
    rollData.difficulte = rollData.rune?.system?.seuil || 0
    rollData.runemode = "prononcer"
    rollData.runeame = 1
    console.log("runeData", rollData)
    await MournbladeRollDialog.create(this, rollData)
  }

  /* -------------------------------------------- */
  async rollSortilege() {
    const runes = this.getRunes()
    if (runes.length < 2) {
      ui.notifications.warn("Il faut au moins deux Runes pour lancer un Sortilège.")
      return
    }
    const comp = this.items.find(c => c.type == "competence" && c.name.toLowerCase() == "savoir : runes")
    if (!comp) {
      ui.notifications.warn("La compétence Savoir : Runes n'a pas été trouvée, abandon.")
      return
    }
    let rollData = this.getCommonRollData("cla", undefined, "Savoir : Runes")
    rollData.isSortilege = true
    rollData.difficulte = 0
    rollData.runemode = "prononcer"
    rollData.runeame = 0
    await MournbladeRollDialog.createSortilege(this, rollData)
  }

  /* -------------------------------------------- */
  async preparePotion() {
    const runes = this.getRunes()
    if (runes.length === 0) {
      ui.notifications.warn("Aucune Rune disponible pour préparer une potion.")
      return
    }
    const comp = this.items.find(c => c.type == "competence" && c.name.toLowerCase() == "savoir : runes")
    if (!comp) {
      ui.notifications.warn("La compétence Savoir : Runes n'a pas été trouvée, abandon.")
      return
    }
    let rollData = this.getCommonRollData("cla", comp._id)
    rollData.isPotion = true
    rollData.mainDice = "1d10"

    // Optionally cap by Savoir:Haut-Parler and Savoir:Alchimie
    const hautParlerComp = this.items.find(c => c.type == "competence" && c.name.toLowerCase() == "savoir : haut-parler")
    const alchimieComp = this.items.find(c => c.type == "competence" && c.name.toLowerCase() == "savoir : alchimie")
    if (hautParlerComp) rollData.limitHautParlerValue = hautParlerComp.system.niveau
    if (alchimieComp) rollData.limitAlchimieValue = alchimieComp.system.niveau

    await MournbladeRollDialog.createPotion(this, rollData)
  }

  /* -------------------------------------------- */
  async invoquerElementaire() {
    const persuasionComp = this.items.find(c => c.type == "competence" && c.name.toLowerCase() == "persuasion")
    if (!persuasionComp) {
      ui.notifications.warn("La compétence Persuasion est requise pour invoquer un Élémentaire.")
      return
    }
    let rollData = this.getCommonRollData("pre", persuasionComp._id)
    rollData.isInvocationElementaire = true
    rollData.mainDice = "1d10"

    const hautParlerComp = this.items.find(c => c.type == "competence" && c.name.toLowerCase() == "savoir : haut-parler")
    const seigneursElemComp = this.items.find(c => c.type == "competence" && c.name.toLowerCase() == "savoir : seigneurs élémentaires")
    if (hautParlerComp) rollData.hautParlerNiveau = hautParlerComp.system.niveau
    if (seigneursElemComp) rollData.seigneursElemNiveau = seigneursElemComp.system.niveau

    await MournbladeInvocationDialog.create(this, rollData)
  }

  /* -------------------------------------------- */
  async bannirElementaire(invocIndex) {
    const invocations = foundry.utils.duplicate(this.system.invocationsElementaires || [])
    const invoc = invocations[invocIndex]
    if (!invoc) return

    // Free the blocked soul
    await this.subPointsAme("prononcer", -invoc.soulCost)

    // Delete the created actor if it still exists
    if (invoc.actorId) {
      const createdActor = game.actors.get(invoc.actorId)
      if (createdActor) await createdActor.delete()
    }

    // Remove from the list
    invocations.splice(invocIndex, 1)
    await this.update({ "system.invocationsElementaires": invocations })
    ui.notifications.info(`L'Élémentaire ${invoc.actorName} a été banni. ${invoc.soulCost} points d'Âme libérés.`)
  }

  /* -------------------------------------------- */
  async invoquerDemon() {
    const normalize = str => str.toLowerCase()
      .replace(/œ/g, "oe").replace(/æ/g, "ae")
      .normalize("NFD").replace(/[\u0300-\u036f]/g, "")
      .replace(/[^a-z0-9]+/g, " ").trim()
    const hasKeywords = (item, ...words) => {
      const n = normalize(item.name)
      return words.every(w => n.includes(normalize(w)))
    }
    const coercitionComp = this.items.find(c => c.type === "competence" && hasKeywords(c, "coercition"))
    if (!coercitionComp) {
      ui.notifications.warn("La compétence Coercition est requise pour invoquer un Démon.")
      return
    }
    const isChaotique = this.system.balance.chaos > this.system.balance.loi
    const hasOeilSorcier = this.items.some(c => (c.type === "capacite" || c.type === "don") && hasKeywords(c, "oeil", "sorcier"))
    const hasRuneChaos = this.items.some(i => i.type === "rune" && hasKeywords(i, "chaos"))
    if (!isChaotique || !hasOeilSorcier || !hasRuneChaos) {
      const missing = []
      if (!isChaotique) missing.push("alignement chaotique (Chaos > Loi)")
      if (!hasOeilSorcier) missing.push("Capacité/Don Œil du Sorcier")
      if (!hasRuneChaos) missing.push("Rune du Chaos")
      ui.notifications.warn(`Prérequis manquants pour l'invocation démoniaque : ${missing.join(", ")}.`)
    }

    let rollData = this.getCommonRollData("tre", coercitionComp._id)
    rollData.isInvocationDemon = true
    rollData.mainDice = "1d10"

    await MournbladeInvocationDemonDialog.create(this, rollData)
  }

  /* -------------------------------------------- */
  async libererDemon(invocIndex) {
    const invocations = foundry.utils.duplicate(this.system.invocationsDemons || [])
    const invoc = invocations[invocIndex]
    if (!invoc) return

    invocations.splice(invocIndex, 1)
    await this.update({ "system.invocationsDemons": invocations })
    ui.notifications.info(`Le Démon ${invoc.demonName ?? "invoqué"} a été libéré.`)
  }

  /* -------------------------------------------- */
  async invoquerEspritLoi() {
    const normalize = str => str.toLowerCase()
      .replace(/œ/g, "oe").replace(/æ/g, "ae")
      .normalize("NFD").replace(/[\u0300-\u036f]/g, "")
      .replace(/[^a-z0-9]+/g, " ").trim()
    const hasKeywords = (item, ...words) => {
      const n = normalize(item.name)
      return words.every(w => n.includes(normalize(w)))
    }

    const persuasionComp = this.items.find(c => c.type === "competence" && hasKeywords(c, "persuasion"))
    const isLoyal = this.system.balance.loi > this.system.balance.chaos
    const hasRuneLoi = this.items.some(i => i.type === "rune" && hasKeywords(i, "loi"))

    if (!isLoyal || !hasRuneLoi) {
      const missing = []
      if (!isLoyal) missing.push("alignement loyal (Loi > Chaos)")
      if (!hasRuneLoi) missing.push("Rune de la Loi")
      ui.notifications.warn(`Prérequis manquants : ${missing.join(", ")}.`)
    }

    const rollData = this.getCommonRollData("tre", persuasionComp?._id ?? null)
    rollData.isInvocationEsprit = true
    rollData.mainDice = "1d10"

    await MournbladeInvocationEspritDialog.create(this, rollData)
  }

  /* -------------------------------------------- */
  async enchanter(itemId) {
    const item = this.items.get(itemId)
    if (!item) return
    if (!["arme", "equipement", "protection", "bouclier"].includes(item.type)) {
      ui.notifications.warn("Seules les armes, équipements, protections et boucliers peuvent être enchantés.")
      return
    }
    await MournbladeEnchantementDialog.create(this, item)
  }

  /* -------------------------------------------- */
  async rollArmeOffensif(armeId) {
    let arme = this.items.get(armeId)
    if (arme.type == "arme") {
      arme = this.prepareArme(arme)
    }
    if (arme.type == "bouclier") {
      arme = this.prepareBouclier(arme)
    }
    let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id)
    rollData.arme = arme
    rollData.typeAttaque = "assaut"
    rollData.typeCouvert = "aucun"
    rollData.hasDesavantageBonus = true
    rollData.visee = false
    rollData.ciblecourt = false
    rollData.cibleconsciente = false
    // Do not display difficulte if defense weapon or distance
    if (rollData.armeDefense || rollData.arme.system.isDistance) {
      rollData.selectDifficulte = false
      rollData.difficulte = (rollData.arme.system.isDistance) ? 0 : rollData.difficulte
    }
    console.log("ARME!", rollData)
    this.depenseRessources(arme)
    await MournbladeRollDialog.create(this, rollData)
  }

  /* -------------------------------------------- */
  async rollAssomer() {
    let rollData = this.getCommonRollData("adr", undefined, "Filouterie")
    rollData.typeAttaque = "assomer"
    rollData.typeCouvert = "aucun"
    rollData.hasDesavantageBonus = true
    if (rollData.defender) {
      rollData.selectDifficulte = false
      rollData.difficulte = rollData.defender.system.attributs.tre.value * 2
    }
    console.log("Assomer!", rollData)
    await MournbladeRollDialog.create(this, rollData)
  }
  /* -------------------------------------------- */
  async rollFuir() {
    let rollData = this.getCommonRollData("adr", undefined, "Mouvements")
    rollData.typeAttaque = "fuir"
    rollData.typeCouvert = "aucun"
    rollData.hasDesavantageBonus = true
    if (rollData.defender) {
      rollData.selectDifficulte = false
      let comp = rollData.defender.items.find(it => it.type == "competence" && it.name.toLowerCase() == "mouvements")
      rollData.difficulte = rollData.defender.system.attributs.adr.value + ((comp) ? comp.system.niveau : rollData.defender.system.attributs.adr.value)
    }
    console.log("Fuir!", rollData)
    await MournbladeRollDialog.create(this, rollData)
  }
  /* -------------------------------------------- */
  async rollImmobiliser() {
    let rollData = this.getCommonRollData("pui", undefined, "Mêlée")
    rollData.typeAttaque = "immobiliser"
    rollData.typeCouvert = "aucun"
    rollData.hasDesavantageBonus = true
    if (rollData.defender) {
      rollData.selectDifficulte = false
      rollData.difficulte = rollData.defenderCombatValues.defenseTotal
    }
    console.log("Immobiliser!", rollData)
    await MournbladeRollDialog.create(this, rollData)
  }
  /* -------------------------------------------- */
  async rollArmeSpecial(armeId) {
    let arme = this.items.get(armeId)
    if (arme) {
      MournbladeUtility.createChatWithRollMode("GM", {
        content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-mournblade/templates/chat-display-description.hbs`, arme)
      }, arme)
      this.depenseRessources(arme)
    }
  }

  /* -------------------------------------------- */
  async rollArmeDegats(armeId) {
    let arme = this.items.get(armeId)
    if (arme.type == "arme") {
      arme = this.prepareArme(arme)
    }
    if (arme.type == "bouclier") {
      arme = this.prepareBouclier(arme)
    }
    //Unused rollData.degatsFormula = arme.system.totalDegats
    let roll
    try {
      roll = await new Roll(arme.system.totalDegats).evaluate()
    } catch (err) {
      ui.notifications.error(`Formule de dégâts invalide : ${arme.system.totalDegats}`)
      console.error("rollArmeDegats error:", err)
      return
    }
    await MournbladeUtility.showDiceSoNice(roll, game.settings.get("core", "rollMode"));
    let rollData = {
      degatsFormula: arme.system.totalDegats,
      arme: arme,
      finalResult: roll.total,
      alias: this.name,
      actorImg: this.img,
      actorId: this.id,
      actionImg: arme.img,
    }
    MournbladeUtility.createChatWithRollMode(rollData.alias, {
      content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-mournblade/templates/chat-degats-result-v2.hbs`, rollData)
    })

  }
}
