import { MournbladeUtility } from "../mournblade-utility.js"

/**
 * Dialogue de jet de dé pour Mournblade - Version DialogV2
 */
export class MournbladeRollDialog {

  /**
   * Create and display the roll dialog
   * @param {MournbladeActor} actor - The actor making the roll
   * @param {Object} rollData - Data for the roll
   * @returns {Promise<MournbladeRollDialog>}
   */
  static async create(actor, rollData) {
    // Préparer le contexte pour le template
    const context = {
      ...rollData,
      difficulte: String(rollData.difficulte || 0),
      img: actor.img,
      name: actor.name,
      config: game.system.mournblade.config,
    }

    // Si attrKey est "tochoose", préparer la liste des attributs sélectionnables
    if (rollData.attrKey === "tochoose") {
      context.selectableAttributes = actor.system.attributs
    }

    // Rendre le template en HTML
    const content = await foundry.applications.handlebars.renderTemplate(
      "systems/fvtt-mournblade/templates/roll-dialog-v2.hbs",
      context
    )

    // Utiliser DialogV2.wait avec le HTML rendu
    return foundry.applications.api.DialogV2.wait({
      window: { title: "Test de Capacité", icon: "fa-solid fa-dice-d20" },
      classes: ["mournblade-roll-dialog"],
      position: { width: 500 },
      modal: false,
      content,
      buttons: [
        {
          action: "rolld10",
          label: "Lancer 1d10",
          icon: "fa-solid fa-dice-d10",
          default: true,
          callback: async (event, button, dialog) => {
            this._updateRollDataFromForm(rollData, button.form.elements, actor)
            rollData.mainDice = "1d10"
            await MournbladeUtility.rollMournblade(rollData)
          }
        },
        {
          action: "rolld20",
          label: "Lancer 1d20",
          icon: "fa-solid fa-dice-d20",
          callback: async (event, button, dialog) => {
            this._updateRollDataFromForm(rollData, button.form.elements, actor)
            rollData.mainDice = "1d20"
            await MournbladeUtility.rollMournblade(rollData)
          }
        },
      ],
      rejectClose: false,
    })
  }

  /**
   * Create and display the sortilège (multi-rune spell) roll dialog
   * @param {MournbladeActor} actor
   * @param {Object} rollData
   */
  static async createSortilege(actor, rollData) {
    const ameDisponible = Math.max(1, (actor.system.ame.currentmax - actor.system.ame.value))
    const context = {
      ...rollData,
      img: actor.img,
      name: actor.name,
      config: game.system.mournblade.config,
      runes: actor.getRunes(),
      runemode: "prononcer",
      ameDisponible,
      ameOptions: Array.from({ length: ameDisponible }, (_, i) => i + 1),
      modOptions: Array.from({ length: 21 }, (_, i) => i - 10),
    }

    const content = await foundry.applications.handlebars.renderTemplate(
      "systems/fvtt-mournblade/templates/dialog-sortilege.hbs",
      context
    )

    // Attach dynamic recalculation after render
    Hooks.once("renderDialogV2", (_app, html) => {
      const form = html.querySelector ? html : html[0]
      MournbladeRollDialog._attachSortilegeListeners(form)
    })

    return foundry.applications.api.DialogV2.wait({
      window: { title: "Lancer un Sortilège", icon: "fa-solid fa-star-of-david" },
      classes: ["mournblade-roll-dialog"],
      position: { width: 520 },
      modal: false,
      content,
      buttons: [
        {
          action: "rolld10",
          label: "Lancer 1d10",
          icon: "fa-solid fa-dice-d10",
          default: true,
          callback: async (event, button, dialog) => {
            this._updateSortilegeRollData(rollData, button.form.elements, actor)
            rollData.mainDice = "1d10"
            await MournbladeUtility.rollSortilege(rollData)
          }
        },
        {
          action: "rolld20",
          label: "Lancer 1d20",
          icon: "fa-solid fa-dice-d20",
          callback: async (event, button, dialog) => {
            this._updateSortilegeRollData(rollData, button.form.elements, actor)
            rollData.mainDice = "1d20"
            await MournbladeUtility.rollSortilege(rollData)
          }
        },
      ],
      rejectClose: false,
    })
  }

  /**
   * Open the potion preparation dialog
   * @param {MournbladeActor} actor
   * @param {object} rollData
   */
  static async createPotion(actor, rollData) {
    const ameDisponible = Math.max(1, (actor.system.ame.currentmax - actor.system.ame.value))
    const context = {
      ...rollData,
      img: actor.img,
      name: actor.name,
      config: game.system.mournblade.config,
      runes: actor.getRunes(),
      ameDisponible,
      ameOptions: Array.from({ length: ameDisponible }, (_, i) => i + 1),
      modOptions: Array.from({ length: 21 }, (_, i) => i - 10),
    }

    const content = await foundry.applications.handlebars.renderTemplate(
      "systems/fvtt-mournblade/templates/dialog-potion.hbs",
      context
    )

    Hooks.once("renderDialogV2", (_app, html) => {
      const form = html.querySelector ? html : html[0]
      MournbladeRollDialog._attachPotionListeners(form)
    })

    return foundry.applications.api.DialogV2.wait({
      window: { title: "Préparer une Potion", icon: "fa-solid fa-flask" },
      classes: ["mournblade-roll-dialog"],
      position: { width: 520 },
      modal: false,
      content,
      buttons: [
        {
          action: "preparer",
          label: "Préparer",
          icon: "fa-solid fa-flask",
          default: true,
          callback: async (event, button, dialog) => {
            MournbladeRollDialog._updatePotionRollData(rollData, button.form.elements, actor)
            await MournbladeUtility.rollPotion(rollData)
          }
        },
      ],
      rejectClose: false,
    })
  }

  /**
   * Attach dynamic recalculation listeners to the potion dialog
   * @param {HTMLElement} html
   */
  static _attachPotionListeners(html) {
    const recalculate = () => {
      const radioChecked = html.querySelector('.potion-rune-radio:checked')
      const runeRow = radioChecked?.closest('[data-seuil]')
      const seuil = parseInt(runeRow?.dataset.seuil ?? 0)
      const pa = parseInt(html.querySelector('[name="pointsAme"]')?.value ?? 1)
      const mod = parseInt(html.querySelector('[name="modificateur"]')?.value ?? 0)

      const difficulteEl = html.querySelector('#potion-difficulte')
      if (difficulteEl) difficulteEl.textContent = (seuil + pa) + (mod !== 0 ? ` (mod ${mod > 0 ? '+' : ''}${mod})` : '')

      const tempsEl = html.querySelector('#potion-temps')
      if (tempsEl) {
        const heures = Math.max(1, Math.ceil(pa / 3))
        tempsEl.textContent = heures === 1 ? '1 heure' : `${heures} heures`
      }
    }

    html.querySelectorAll('.potion-rune-radio, [name="pointsAme"]').forEach(el => {
      el.addEventListener('change', recalculate)
    })
    recalculate()
  }

  /**
   * Update rollData from the potion dialog form elements
   * @param {object} rollData
   * @param {HTMLFormControlsCollection} formElements
   * @param {MournbladeActor} actor
   */
  static _updatePotionRollData(rollData, formElements, actor) {
    const runeId = formElements['rune-selected']?.value
    if (runeId) {
      const rune = actor.getRunes().find(r => r._id === runeId)
      if (rune) {
        rollData.runeId = runeId
        rollData.runeName = rune.name
        rollData.runeImg = rune.img
        rollData.runeSeuil = rune.system.seuil ?? 0
        rollData.runeHautParler = rune.system.hautParler ?? ""
      }
    }
    rollData.pointsAme = parseInt(formElements['pointsAme']?.value ?? 1)
    rollData.forme = formElements['forme']?.value ?? "liquide"
    rollData.modificateur = parseInt(formElements['modificateur']?.value ?? 0)
  }

  /**
   * Attach dynamic recalculation listeners to the sortilège dialog
   * @param {HTMLElement} html
   */
  static _attachSortilegeListeners(html) {
    const recalculate = () => {
      const checkboxes = html.querySelectorAll('.sortilege-rune-checkbox:checked')
      const modeSelect = html.querySelector('[name="runemode"]')
      const mode = modeSelect?.value ?? "prononcer"

      let maxSeuil = 0
      let totalAme = 0
      let totalActions = 0
      let count = 0

      // Enable/disable points inputs based on checkbox state
      html.querySelectorAll('.sortilege-rune-checkbox').forEach(cb => {
        const row = cb.closest('.sortilege-rune-row')
        const pointsInput = row?.querySelector('.sortilege-rune-points')
        if (pointsInput) pointsInput.disabled = !cb.checked
      })

      checkboxes.forEach(cb => {
        const row = cb.closest('.sortilege-rune-row')
        const seuil = Number(row?.dataset.seuil ?? 0)
        const pts = Number(row?.querySelector('.sortilege-rune-points')?.value ?? 1)
        if (seuil > maxSeuil) maxSeuil = seuil
        totalAme += pts
        totalActions += Math.ceil(pts / 3) * (mode === "inscrire" ? 2 : 1)
        count++
      })

      const difficulte = count > 0 ? maxSeuil + (count - 1) : 0
      html.querySelector('#sortilege-difficulte').textContent = count > 0 ? difficulte : '—'
      html.querySelector('#sortilege-total-ame').textContent = totalAme
      html.querySelector('#sortilege-actions').textContent = totalActions
    }

    html.querySelectorAll('.sortilege-rune-checkbox, .sortilege-rune-points, [name="runemode"]')
      .forEach(el => el.addEventListener('change', recalculate))
  }

  /**
   * Extract sortilège data from the form
   * @param {Object} rollData
   * @param {HTMLFormControlsCollection} formElements
   * @param {MournbladeActor} actor
   */
  static _updateSortilegeRollData(rollData, formElements, actor) {
    rollData.runemode = formElements.runemode?.value ?? "prononcer"
    rollData.modificateur = Number(formElements.modificateur?.value ?? 0)
    rollData.runeautocible = formElements.runeautocible?.checked ?? false

    // Collect selected runes with their soul points
    const runes = actor.getRunes()
    rollData.sortilegeRunes = []
    for (const rune of runes) {
      const checkbox = formElements[`rune-selected-${rune._id}`]
      if (checkbox?.checked) {
        const pts = Math.max(1, Number(formElements[`rune-points-${rune._id}`]?.value ?? 1))
        rollData.sortilegeRunes.push({
          id: rune._id,
          name: rune.name,
          img: rune.img,
          seuil: rune.system.seuil,
          formule: rune.system.formule,
          pts,
        })
      }
    }

    if (rollData.sortilegeRunes.length === 0) return

    const maxSeuil = Math.max(...rollData.sortilegeRunes.map(r => r.seuil))
    rollData.difficulte = maxSeuil + (rollData.sortilegeRunes.length - 1)
    rollData.runeame = rollData.sortilegeRunes.reduce((s, r) => s + r.pts, 0)
  }

  /**
   * @param {Object} rollData - L'objet rollData à mettre à jour
   * @param {HTMLFormControlsCollection} formElements - Les éléments du formulaire
   * @param {MournbladeActor} actor - L'acteur pour récupérer les attributs
   * @private
   */
  static _updateRollDataFromForm(rollData, formElements, actor) {
    // Attributs
    if (formElements.attrKey) {
      rollData.attrKey = formElements.attrKey.value
      if (rollData.attrKey !== "tochoose" && actor) {
        rollData.attr = foundry.utils.duplicate(actor.system.attributs[rollData.attrKey])
        rollData.actionImg = "systems/fvtt-mournblade/assets/icons/" + actor.system.attributs[rollData.attrKey].labelnorm + ".webp"
      }
    }

    // Modificateurs de base
    if (formElements.difficulte) {
      rollData.difficulte = Number(formElements.difficulte.value)
    }
    if (formElements.modificateur) {
      rollData.modificateur = Number(formElements.modificateur.value)
    }

    // Runes
    if (formElements.runemode) {
      rollData.runemode = String(formElements.runemode.value)
    }
    if (formElements.runeame) {
      rollData.runeame = Number(formElements.runeame.value)
    }
    if (formElements.runeautocible !== undefined) {
      rollData.runeautocible = formElements.runeautocible.checked
    }

    // Combat mêlée
    if (formElements.typeAttaque) {
      rollData.typeAttaque = String(formElements.typeAttaque.value)
    }
    if (formElements.isMonte !== undefined) {
      rollData.isMonte = formElements.isMonte.checked
    }

    // Combat distance
    if (formElements.visee !== undefined) {
      rollData.visee = formElements.visee.checked
    }
    if (formElements.cibleconsciente !== undefined) {
      rollData.cibleconsciente = formElements.cibleconsciente.checked
    }
    if (formElements.ciblecourt !== undefined) {
      rollData.ciblecourt = formElements.ciblecourt.checked
    }
    if (formElements.typeCouvert) {
      rollData.typeCouvert = String(formElements.typeCouvert.value)
    }

    // Désavantages
    if (!rollData.desavantages) rollData.desavantages = {}
    
    if (formElements.cibleausol !== undefined) {
      rollData.desavantages.cibleausol = formElements.cibleausol.checked
    }
    if (formElements.cibledesarmee !== undefined) {
      rollData.desavantages.cibledesarmee = formElements.cibledesarmee.checked
    }
    if (formElements.ciblerestreint !== undefined) {
      rollData.desavantages.ciblerestreint = formElements.ciblerestreint.checked
    }
    if (formElements.cibleimmobilisée !== undefined) {
      rollData.desavantages.cibleimmobilisée = formElements.cibleimmobilisée.checked
    }
    if (formElements.ciblesurplomb !== undefined) {
      rollData.desavantages.ciblesurplomb = formElements.ciblesurplomb.checked
    }

    // Double D20
    if (formElements.doubleD20 !== undefined) {
      rollData.doubleD20 = formElements.doubleD20.checked
    }

    // Modifiers
    if (rollData.modifiers) {
      rollData.modifiers.forEach((modifier, idx) => {
        const checkbox = formElements[`apply-modifier-${idx}`]
        if (checkbox) {
          modifier.system.apply = checkbox.checked
        }
      })
    }
  }
}
