/**
 * Chroniques de l'Étrange — Système FoundryVTT
 *
 * Chroniques de l'Étrange est un jeu de rôle édité par Antre-Monde Éditions.
 * Ce système FoundryVTT est une implémentation indépendante et n'est pas
 * affilié à Antre-Monde Éditions,
 * mais a été réalisé avec l'autorisation d'Antre-Monde Éditions.
 *
 * @author    LeRatierBretonnien
 * @copyright 2024–2026 LeRatierBretonnien
 * @license   CC BY-NC-SA 4.0 – https://creativecommons.org/licenses/by-nc-sa/4.0/
 */

/**
 * Initiative determination system for Chroniques de l'Étrange.
 *
 * PJ formula:  Initiative = Prouesse + Première action (compétence/ressource/magie)
 * PNJ formula: Initiative = Aptitude physique + Première action (aptitude)
 *
 * Range 1-24 ; anti-initiative = 25 − initiative.
 * Combat order is ascending (low initiative acts first).
 */

const PC_PROMPT_TEMPLATE  = "systems/fvtt-chroniques-de-l-etrange/templates/form/cde-initiative-prompt.html"
const NPC_PROMPT_TEMPLATE = "systems/fvtt-chroniques-de-l-etrange/templates/form/cde-initiative-prompt-npc.html"
const RESULT_TEMPLATE     = "systems/fvtt-chroniques-de-l-etrange/templates/form/cde-initiative-result.html"

/** Skills, resources and magics available as "première action" for a PC. */
function buildPCOptions(sys) {
  const sk = sys.skills ?? {}
  const rs = sys.resources ?? {}
  const mg = sys.magics ?? {}
  return [
    { key: "art",              label: game.i18n.localize("CDE.Art"),              value: sk.art?.value              ?? 0 },
    { key: "investigation",    label: game.i18n.localize("CDE.Investigation"),    value: sk.investigation?.value    ?? 0 },
    { key: "erudition",        label: game.i18n.localize("CDE.Erudition"),        value: sk.erudition?.value        ?? 0 },
    { key: "knavery",          label: game.i18n.localize("CDE.Knavery"),          value: sk.knavery?.value          ?? 0 },
    { key: "wordliness",       label: game.i18n.localize("CDE.Wordliness"),       value: sk.wordliness?.value       ?? 0 },
    { key: "prowess",          label: game.i18n.localize("CDE.Prowess"),          value: sk.prowess?.value          ?? 0 },
    { key: "sciences",         label: game.i18n.localize("CDE.Sciences"),         value: sk.sciences?.value         ?? 0 },
    { key: "technologies",     label: game.i18n.localize("CDE.Technologies"),     value: sk.technologies?.value     ?? 0 },
    { key: "kungfu",           label: game.i18n.localize("CDE.KungFu"),           value: sk.kungfu?.value           ?? 0 },
    { key: "rangedcombat",     label: game.i18n.localize("CDE.RangedCombat"),     value: sk.rangedcombat?.value     ?? 0 },
    { key: "supply",           label: game.i18n.localize("CDE.Supply"),           value: rs.supply?.value           ?? 0 },
    { key: "inquiry",          label: game.i18n.localize("CDE.Inquiry"),          value: rs.inquiry?.value          ?? 0 },
    { key: "influence",        label: game.i18n.localize("CDE.Influence"),        value: rs.influence?.value        ?? 0 },
    { key: "internalcinnabar", label: game.i18n.localize("CDE.InternalCinnabar"), value: mg.internalcinnabar?.value ?? 0 },
    { key: "alchemy",          label: game.i18n.localize("CDE.Alchemy"),          value: mg.alchemy?.value          ?? 0 },
    { key: "masteryoftheway",  label: game.i18n.localize("CDE.MasteryOfTheWay"),  value: mg.masteryoftheway?.value  ?? 0 },
    { key: "exorcism",         label: game.i18n.localize("CDE.Exorcism"),         value: mg.exorcism?.value         ?? 0 },
    { key: "geomancy",         label: game.i18n.localize("CDE.Geomancy"),         value: mg.geomancy?.value         ?? 0 },
  ]
}

/** Aptitudes available as "première action" for an NPC. */
function buildNPCOptions(sys) {
  const ap = sys.aptitudes ?? {}
  return [
    { key: "physical",  label: game.i18n.localize("CDE.Physical"),  value: ap.physical?.value  ?? 0 },
    { key: "martial",   label: game.i18n.localize("CDE.Martial"),   value: ap.martial?.value   ?? 0 },
    { key: "mental",    label: game.i18n.localize("CDE.Mental"),    value: ap.mental?.value    ?? 0 },
    { key: "social",    label: game.i18n.localize("CDE.Social"),    value: ap.social?.value    ?? 0 },
    { key: "spiritual", label: game.i18n.localize("CDE.Spiritual"), value: ap.spiritual?.value ?? 0 },
  ]
}

/** Parse the dialog element and extract firstaction + modifier. */
function readInitFields(dialog) {
  const root = dialog.element ?? dialog
  const selectedKey = root.querySelector("select[name='firstaction']")?.value ?? ""
  const modifier    = parseInt(root.querySelector("input[name='modifier']")?.value ?? "0", 10) || 0
  return { selectedKey, modifier }
}

/** Post a styled initiative chat message. */
async function sendInitChatMessage({ actor, baseName, baseValue, actionName, actionValue, modifier, initiative, antiInitiative }) {
  const html = await foundry.applications.handlebars.renderTemplate(RESULT_TEMPLATE, {
    actorName:     actor.name,
    actorImg:      actor.img,
    baseName,
    baseValue,
    actionName,
    actionValue,
    modifier,
    hasModifier:   modifier !== 0,
    initiative,
    antiInitiative,
  })
  await ChatMessage.create({
    user:    game.user.id,
    speaker: ChatMessage.getSpeaker({ actor }),
    content: html,
  })
}

/**
 * Open the PC initiative dialog, compute initiative (Prouesse + Première action + modificateur)
 * and update the actor, then post a chat card.
 */
export async function rollInitiativePC(actor) {
  const sys       = actor.system
  const prowess   = sys.skills?.prowess?.value ?? 0
  const options   = buildPCOptions(sys)
  const baseName  = game.i18n.localize("CDE.Prowess")

  const content = await foundry.applications.handlebars.renderTemplate(PC_PROMPT_TEMPLATE, {
    prowessValue: prowess,
    options,
    modifier: 0,
  })

  const result = await foundry.applications.api.DialogV2.prompt({
    window:      { title: game.i18n.localize("CDE.InitiativeRoll") },
    content,
    rejectClose: false,
    ok: {
      label:    game.i18n.localize("CDE.Validate"),
      callback: (_ev, _btn, dialog) => readInitFields(dialog),
    },
  })
  if (!result) return

  const { selectedKey, modifier } = result
  const selected     = options.find((o) => o.key === selectedKey) ?? options[0]
  const rawValue     = prowess + selected.value + modifier
  const initiative   = Math.max(1, Math.min(24, rawValue))
  const antiInit     = 25 - initiative

  await actor.update({ "system.initiative": initiative })
  await sendInitChatMessage({
    actor,
    baseName,
    baseValue:    prowess,
    actionName:   selected.label,
    actionValue:  selected.value,
    modifier,
    initiative,
    antiInitiative: antiInit,
  })
}

/**
 * Open the NPC initiative dialog, compute initiative (Aptitude physique + Première action + modificateur)
 * and update the actor, then post a chat card.
 */
export async function rollInitiativeNPC(actor) {
  const sys      = actor.system
  const physical = sys.aptitudes?.physical?.value ?? 0
  const options  = buildNPCOptions(sys)
  const baseName = game.i18n.localize("CDE.Physical")

  const content = await foundry.applications.handlebars.renderTemplate(NPC_PROMPT_TEMPLATE, {
    physicalValue: physical,
    options,
    modifier: 0,
  })

  const result = await foundry.applications.api.DialogV2.prompt({
    window:      { title: game.i18n.localize("CDE.InitiativeRoll") },
    content,
    rejectClose: false,
    ok: {
      label:    game.i18n.localize("CDE.Validate"),
      callback: (_ev, _btn, dialog) => readInitFields(dialog),
    },
  })
  if (!result) return

  const { selectedKey, modifier } = result
  const selected     = options.find((o) => o.key === selectedKey) ?? options[0]
  const rawValue     = physical + selected.value + modifier
  const initiative   = Math.max(1, Math.min(24, rawValue))
  const antiInit     = 25 - initiative

  await actor.update({ "system.initiative": initiative })
  await sendInitChatMessage({
    actor,
    baseName,
    baseValue:    physical,
    actionName:   selected.label,
    actionValue:  selected.value,
    modifier,
    initiative,
    antiInitiative: antiInit,
  })
}
