import MGNERoll from "./roll.mjs"
import { SYSTEM_ID } from "../config/system.mjs"

const t = key => game.i18n.localize(key)
const f = (key, data = {}) => game.i18n.format(key, data)
const INITIATIVE_FLAG = "initiativeState"
const SIDE_BONUS = 20
const FLEE_BASE_TARGET = 5
const FLEE_MIN_TARGET = 2

function isPlayerSide(combatant) {
  return Boolean(combatant?.actor?.hasPlayerOwner)
}

function fleeDialogContent() {
  const options = Array.from({ length: FLEE_BASE_TARGET - FLEE_MIN_TARGET + 1 }, (_, index) => {
    const value = index
    return `<option value="${value}">${value}</option>`
  }).join("")

  return `
    <form class="mgne-flee-dialog">
      <div class="form-group">
        <label>${t("MGNE.Combat.StudyActions")}</label>
        <select name="studyActions">${options}</select>
        <p class="notes">${t("MGNE.Combat.StudyHelp")}</p>
      </div>
    </form>
  `
}

export default class MGNECombat extends Combat {
  getFleeCombatant(combatantId = null) {
    if (combatantId) return this.combatants.get(combatantId) ?? null

    const controlledCombatant = canvas.tokens?.controlled?.[0]?.combatant ?? null
    return this.combatant ?? controlledCombatant
  }

  async getInitiativeState() {
    const existing = this.getFlag(SYSTEM_ID, INITIATIVE_FLAG)
    if (existing && Number.isFinite(existing.sideRoll)) return existing

    const sideRoll = await (new Roll("1d6")).evaluate()
    const initiativeState = {
      sideRoll: sideRoll.total,
      playersActFirst: sideRoll.total >= 4,
    }

    await this.setFlag(SYSTEM_ID, INITIATIVE_FLAG, initiativeState)
    await ChatMessage.create({
      speaker: ChatMessage.getSpeaker(),
      content: `<p>${f("MGNE.Initiative.SideRoll", { roll: initiativeState.sideRoll })}</p><p>${t(initiativeState.playersActFirst ? "MGNE.Initiative.PlayersFirst" : "MGNE.Initiative.EnemiesFirst")}</p><p>${t("MGNE.Initiative.TieBreak")}</p>`,
    })
    return initiativeState
  }

  async rollInitiative(ids, { updateTurn = true } = {}) {
    const combatantIds = typeof ids === "string" ? [ids] : Array.from(ids ?? [])
    if (!combatantIds.length) return this

    const currentCombatantId = this.combatant?.id ?? null
    const initiativeState = await this.getInitiativeState()
    const updates = []

    for (const id of combatantIds) {
      const combatant = this.combatants.get(id)
      if (!combatant) continue

      const agility = combatant.actor?.system?.abilities?.agility?.value ?? 0
      const roll = await (new Roll("1d6 + @agility", { agility })).evaluate()
      const actsWithPriority = isPlayerSide(combatant) === initiativeState.playersActFirst
      updates.push({
        _id: id,
        initiative: roll.total + (actsWithPriority ? SIDE_BONUS : 0),
      })
    }

    if (updates.length) await this.updateEmbeddedDocuments("Combatant", updates)

    if (updateTurn && currentCombatantId) {
      const turn = this.turns.findIndex(combatant => combatant.id === currentCombatantId)
      if (turn >= 0) await this.update({ turn })
    }

    return this
  }

  async rollFlee({ combatantId = null } = {}) {
    const combatant = this.getFleeCombatant(combatantId)
    if (!combatant?.actor) {
      ui.notifications.warn(t("MGNE.Combat.FleeNoCombatant"))
      return null
    }

    const dialogData = await foundry.applications.api.DialogV2.wait({
      window: { title: t("MGNE.Combat.Flee") },
      classes: ["mgne", "roll-dialog"],
      content: fleeDialogContent(),
      buttons: [{
        label: t("MGNE.Combat.Flee"),
        icon: "fa-solid fa-person-running",
        callback: (_event, button) => {
          const value = Number.parseInt(button.form?.elements.studyActions?.value ?? "0", 10)
          return { studyActions: Math.max(0, Math.min(FLEE_BASE_TARGET - FLEE_MIN_TARGET, value || 0)) }
        },
      }],
      rejectClose: false,
    })

    if (!dialogData) return null

    const studyActions = dialogData.studyActions ?? 0
    const target = Math.max(FLEE_MIN_TARGET, FLEE_BASE_TARGET - studyActions)
    const roll = await (new Roll("1d6")).evaluate()
    const escaped = roll.total >= target

    if (escaped) {
      await combatant.delete()
    } else {
      await combatant.actor.update({ "system.hp.value": 0 })
      await combatant.update({ defeated: true })
    }

    await MGNERoll.createActionCard({
      mode: "flee",
      actor: combatant.actor,
      label: f("MGNE.Roll.FleeLabel", { actor: combatant.name }),
      subtitle: f("MGNE.Roll.FleeSubtitle", { target }),
      roll,
      outcome: t(escaped ? "MGNE.Roll.FleeEscaped" : "MGNE.Roll.FleeKilled"),
      specialText: studyActions > 0
        ? f("MGNE.Roll.FleeStudyActions", { count: studyActions })
        : t("MGNE.Roll.FleeNoStudyActions"),
    })

    return { combatant, roll, escaped, target, studyActions }
  }
}
