import { VermineUtils } from "../roll.mjs"
import { VermineExchange } from "../exchange.mjs"

const { HandlebarsApplicationMixin } = foundry.applications.api

/**
 * Dialogue de jet simplifié pour les PNJ.
 *
 * Un PNJ n'a ni caractéristiques ni compétences : toutes ses actions sont
 * résolues par une valeur unique dérivée de son Profil (Menace / Expérience /
 * Rôle), exposée dans system.computed. Ce dialogue fixe le pool selon le type
 * de jet (Action, Spécialité, Attaque ou Réaction) et n'offre que la difficulté,
 * le handicap et les bonus simples.
 *
 * Utilisé par :
 * - la fiche PNJ (boutons de jet rapide Action / Spécialité / Réaction) ;
 * - la défense des PNJ dans les échanges de coups (mode verrouillé).
 */
export default class NpcRollDialog extends HandlebarsApplicationMixin(foundry.applications.api.ApplicationV2) {

  #actor

  get title() {
    return game.i18n.localize("VERMINE.roll")
  }

  static DEFAULT_OPTIONS = {
    classes: ["vermine-roll"],
    tag: "form",
    window: {
      icon: "fas fa-dice-d10",
      resizable: false
    },
    position: {
      width: 520,
      height: 600
    },
    actions: {
      roll: NpcRollDialog.#onRoll,
      cancel: NpcRollDialog.#onCancel
    }
  }

  static PARTS = {
    main: { template: "systems/vermine2047/templates/dialogs/npc-roll-dialog.hbs" }
  }

  static async create(data = {}) {
    const actor = data.actor instanceof Actor ? data.actor : await game.actors.get(data.actorId)
    if (!actor) {
      ui.notifications.warn(game.i18n.localize("VERMINE.error_no_actor_selected"))
      return null
    }
    return new NpcRollDialog({
      actor,
      rolltype: data.rolltype ?? "action",
      locks: data.locks ?? null,
      defense: data.defense ?? null
    })
  }

  constructor(options = {}) {
    super(options)
    this.#actor = options.actor
    this.rolltype = options.rolltype ?? "action"
    this.locks = options.locks ?? null
    this.defense = options.defense ?? null
  }

  // ── Getters ──────────────────────────────────────────────────────────

  get computed() { return this.#actor.system?.computed || {} }

  /** Pool de dés selon le type de jet. */
  get pool() {
    const c = this.computed
    switch (this.rolltype) {
      case "specialty": return c.specialties || 0
      case "attack": return c.attack || 0
      case "reaction": return c.reaction || 0
      default: return c.action || 3
    }
  }

  /** Réussites automatiques (bonus de Réaction du rôle). */
  get freeSuccesses() {
    return this.rolltype === "reaction" ? (this.computed.reactionBonus || 0) : 0
  }

  /** Relances : utilisables uniquement sur les attaques ou les Spécialités. */
  get rerolls() {
    if (this.rolltype !== "specialty" && this.rolltype !== "attack") return 0
    return this.computed.rerolls || 0
  }

  get label() {
    const keys = {
      action: "ADVERSITY.action",
      specialty: "ADVERSITY.specialties",
      attack: "ADVERSITY.attack",
      reaction: "ADVERSITY.reaction"
    }
    return game.i18n.localize(keys[this.rolltype] || "VERMINE.roll")
  }

  // ── Rendu ────────────────────────────────────────────────────────────

  async _prepareContext() {
    const difficultyOptions = []
    for (let d = 3; d <= 10; d++) {
      difficultyOptions.push({ difficulty: d, label: String(d) })
    }
    let lockedDifficulty = null
    let defaultDifficulty = 7
    if (this.locks?.difficulty !== undefined && this.locks?.difficulty !== null) {
      lockedDifficulty = parseInt(this.locks.difficulty, 10)
      defaultDifficulty = lockedDifficulty
    }
    return {
      actor: this.#actor,
      system: this.#actor.system,
      config: CONFIG.VERMINE,
      rollLabel: this.label,
      rolltype: this.rolltype,
      pool: this.pool,
      freeSuccesses: this.freeSuccesses,
      rerolls: this.rerolls,
      isDefense: Boolean(this.defense),
      lockedDifficulty,
      difficultyOptions,
      defaultDifficulty,
      speakerId: this.#actor.id,
      availableItems: this.#actor.items.filter(i => i.type === "item")
    }
  }

  async _onRender(context, options) {
    this.element.dataset.actorId = this.#actor.id
    for (const inp of this.element.querySelectorAll("[data-roll]")) {
      inp.addEventListener("change", this.#onInputChange.bind(this))
    }
    this.element.querySelector("#handicap")?.addEventListener("change", () => this.#updateUI())
    // Trait Rapide (n) : le défenseur subit (n) Handicaps sur sa défense.
    if (this.locks?.handicap !== undefined && this.locks?.handicap !== null) {
      const sel = this.#el.querySelector("#handicap")
      if (sel) {
        const locked = parseInt(this.locks.handicap, 10)
        let opt = [...sel.options].find(o => parseInt(o.value, 10) === locked + 1)
        if (!opt) {
          opt = document.createElement("option")
          opt.value = String(locked + 1)
          opt.textContent = game.i18n.localize("VERMINE.handicap") + ` (${locked})`
          sel.appendChild(opt)
        }
        opt.selected = true
      }
    }
    this.#updateUI()
  }

  get #el() { return this.element }

  #getHandicap() {
    const sel = this.#el.querySelector("#handicap")
    return Math.max(0, (parseInt(sel?.value, 10) || 1) - 1)
  }

  #getDifficulty() {
    const sel = this.#el.querySelector("#difficulty")
    return parseInt(sel?.value, 10) || 7
  }

  #getHelped() { return this.#el.querySelector("#helped")?.checked ? 1 : 0 }

  #getGroup() { return parseInt(this.#el.querySelector("#group")?.value, 10) || 0 }

  #getTemporaryMalus() { return parseInt(this.#el.querySelector("#temporary-malus")?.value, 10) || 0 }

  getPoolBreakdown() {
    const help = this.#getHelped()
    const group = this.#getGroup()
    const wound = VermineExchange.woundMalus(this.#actor)
    const tempMalus = this.#getTemporaryMalus()
    const malus = wound + tempMalus
    return { pool: this.pool, help, group, wound, tempMalus, malus, total: Math.max(0, this.pool + help + group - malus) }
  }

  #updateUI() {
    const b = this.getPoolBreakdown()
    const totalEl = this.#el.querySelector("#dice-pool-total")
    if (totalEl) totalEl.textContent = `${b.total}D`
    const bonusEl = this.#el.querySelector("#total-bonus")
    if (bonusEl) bonusEl.textContent = b.help + b.group - b.malus
    const freeEl = this.#el.querySelector("#free-successes")
    if (freeEl) freeEl.textContent = String(this.freeSuccesses)
  }

  #onInputChange() {
    this.#updateUI()
  }

  // ── Actions ──────────────────────────────────────────────────────────

  static async #onCancel(event, target) {
    this.close()
  }

  static async #onRoll(event, target) {
    const label = this.defense
      ? (this.defense.type === "parade"
        ? game.i18n.localize("VERMINE.defense_parade")
        : game.i18n.localize("VERMINE.defense_esquive"))
      : this.label

    const rollParams = {
      actor: this.#actor,
      NoD: this.getPoolBreakdown().total,
      Reroll: this.rerolls,
      difficulty: this.#getDifficulty(),
      handicap: this.#getHandicap(),
      rollLabel: label,
      bonusSuccesses: this.freeSuccesses,
      poolBreakdown: this.getPoolBreakdown(),
      messageFlags: this.defense ? { "vermine-defense": this.defense } : null
    }

    // Fermeture immédiate du dialogue : le jet (et l'animation 3D) continue
    // en arrière-plan sans bloquer la fermeture.
    this.close()

    await VermineUtils.roll(rollParams)
  }
}
