import { ASCII, SYSTEM, SYSTEM_ID, localizeSystemConfig } from "./module/config/system.mjs"
import * as models from "./module/models/_module.mjs"
import * as documents from "./module/documents/_module.mjs"
import * as applications from "./module/applications/_module.mjs"
import MGNERoll from "./module/documents/roll.mjs"

Hooks.once("init", () => {
  console.info(ASCII)
  console.info(`${SYSTEM_ID} | Initializing system`)

  game.mgne = {
    SYSTEM,
    applications,
    documents,
    models,
  }

  CONFIG.Actor.documentClass = documents.MGNEActor
  CONFIG.Actor.dataModels = {
    character: models.MGNECharacter,
    creature: models.MGNECreature,
    companion: models.MGNECompanion,
    party: models.MGNEParty,
  }

  CONFIG.Combat.documentClass = documents.MGNECombat
  CONFIG.Item.documentClass = documents.MGNEItem
  CONFIG.Item.dataModels = {
    weapon: models.MGNEWeapon,
    armor: models.MGNEArmor,
    shield: models.MGNEShield,
    equipment: models.MGNEEquipment,
    "resonance-core": models.MGNEResonanceCore,
    artifact: models.MGNEArtifact,
    feature: models.MGNEFeature,
    "creature-trait": models.MGNECreatureTrait,
  }

  foundry.applications.sheets.ActorSheetV2 && foundry.documents.collections.Actors.unregisterSheet(
    "core",
    foundry.applications.sheets.ActorSheetV2,
    { types: Object.keys(CONFIG.Actor.dataModels) }
  )
  foundry.appv1?.sheets?.ActorSheet && foundry.documents.collections.Actors.unregisterSheet("core", foundry.appv1.sheets.ActorSheet)
  foundry.documents.collections.Actors.registerSheet(SYSTEM_ID, applications.MGNECharacterSheet, { types: ["character"], makeDefault: true, label: SYSTEM.actorTypes.character.label })
  foundry.documents.collections.Actors.registerSheet(SYSTEM_ID, applications.MGNECreatureSheet, { types: ["creature"], makeDefault: true, label: SYSTEM.actorTypes.creature.label })
  foundry.documents.collections.Actors.registerSheet(SYSTEM_ID, applications.MGNECompanionSheet, { types: ["companion"], makeDefault: true, label: SYSTEM.actorTypes.companion.label })
  foundry.documents.collections.Actors.registerSheet(SYSTEM_ID, applications.MGNEPartySheet, { types: ["party"], makeDefault: true, label: SYSTEM.actorTypes.party.label })

  foundry.applications.sheets.ItemSheetV2 && foundry.documents.collections.Items.unregisterSheet(
    "core",
    foundry.applications.sheets.ItemSheetV2,
    { types: Object.keys(CONFIG.Item.dataModels) }
  )
  foundry.appv1?.sheets?.ItemSheet && foundry.documents.collections.Items.unregisterSheet("core", foundry.appv1.sheets.ItemSheet)
  foundry.documents.collections.Items.registerSheet(SYSTEM_ID, applications.MGNEWeaponSheet, { types: ["weapon"], makeDefault: true, label: SYSTEM.itemTypes.weapon.label })
  foundry.documents.collections.Items.registerSheet(SYSTEM_ID, applications.MGNEArmorSheet, { types: ["armor"], makeDefault: true, label: SYSTEM.itemTypes.armor.label })
  foundry.documents.collections.Items.registerSheet(SYSTEM_ID, applications.MGNEShieldSheet, { types: ["shield"], makeDefault: true, label: SYSTEM.itemTypes.shield.label })
  foundry.documents.collections.Items.registerSheet(SYSTEM_ID, applications.MGNEEquipmentSheet, { types: ["equipment"], makeDefault: true, label: SYSTEM.itemTypes.equipment.label })
  foundry.documents.collections.Items.registerSheet(SYSTEM_ID, applications.MGNEResonanceCoreSheet, { types: ["resonance-core"], makeDefault: true, label: SYSTEM.itemTypes["resonance-core"].label })
  foundry.documents.collections.Items.registerSheet(SYSTEM_ID, applications.MGNEArtifactSheet, { types: ["artifact"], makeDefault: true, label: SYSTEM.itemTypes.artifact.label })
  foundry.documents.collections.Items.registerSheet(SYSTEM_ID, applications.MGNEFeatureSheet, { types: ["feature"], makeDefault: true, label: SYSTEM.itemTypes.feature.label })
  foundry.documents.collections.Items.registerSheet(SYSTEM_ID, applications.MGNECreatureTraitSheet, { types: ["creature-trait"], makeDefault: true, label: SYSTEM.itemTypes["creature-trait"].label })

  Handlebars.registerHelper("isEqual", (left, right) => left === right)
  Handlebars.registerHelper("includes", (collection, value) => {
    if (!collection) return false
    if (collection instanceof Set) return collection.has(value)
    if (Array.isArray(collection)) return collection.includes(value)
    return false
  })
})

Hooks.once("setup", () => {
  localizeSystemConfig()
})

Hooks.once("ready", () => {
  console.info(`${SYSTEM_ID} | Ready`)
})

Hooks.on("deleteCombat", (combat) => {
  if (!game.user.isGM) return
  const pcActors = [...new Set(
    combat.combatants
      .filter(c => c.actor?.hasPlayerOwner)
      .map(c => c.actor)
  )]
  const cores = pcActors.flatMap(actor =>
    actor.items.filter(item => item.type === "resonance-core" && !item.system.burnedOut && item.system.usageDie !== "depleted")
  )
  if (!cores.length) return
  const lines = cores.map(c => `<li><strong>${c.parent.name}</strong> — ${c.name} (${c.system.usageDie})</li>`).join("")
  ChatMessage.create({
    content: `<article class="mgne-chat-card mode-check"><div class="chat-card-body"><p class="chat-special">⚙️ ${game.i18n.localize("MGNE.Notification.RollUsageDiceReminder")}</p><ul style="margin:.3rem 0 0 1rem;padding:0">${lines}</ul></div></article>`,
  })
})

Hooks.on("renderCombatTracker", (_app, element) => {
  const root = element instanceof HTMLElement ? element : element?.[0]
  if (!root) return

  const footer = root.querySelector(".combat-controls")
  if (!footer || footer.querySelector(".mgne-flee-control")) return

  const button = document.createElement("button")
  button.type = "button"
  button.className = "combat-control-lg mgne-flee-control"
  button.dataset.action = "mgneFlee"
  button.innerHTML = `<i class="fa-solid fa-person-running" inert></i><span>${game.i18n.localize("MGNE.Combat.Flee")}</span>`
  button.disabled = !game.combat
  button.addEventListener("click", event => {
    event.preventDefault()
    game.combat?.rollFlee()
  })

  footer.append(button)
})

Hooks.on("renderChatMessageHTML", (message, element) => {
  const root = element instanceof HTMLElement ? element : element?.[0]
  if (!root) return

  // Dice tooltip toggle
  root.querySelectorAll("[data-action='toggle-dice-tooltip']").forEach(trigger => {
    trigger.addEventListener("click", () => {
      const tooltip = trigger.closest(".chat-card-body")?.querySelector(".chat-dice-tooltip")
      if (!tooltip) return
      const isHidden = tooltip.hidden
      tooltip.hidden = !isHidden
      trigger.classList.toggle("tooltip-open", isHidden)
    })
  })

  root.querySelectorAll(".mgne-roll-damage-btn").forEach(btn => {
    btn.addEventListener("click", async () => {
      const actorId = btn.dataset.actorId
      const itemId = btn.dataset.itemId
      const actor = game.actors.get(actorId)
      const item = actor?.items.get(itemId)
      if (!actor || !item) {
        ui.notifications.warn(game.i18n.localize("MGNE.Notification.ActorOrItemNotFound"))
        return
      }
      await MGNERoll.rollDamage({ actor, item })
    })
  })

  root.querySelectorAll(".mgne-omen-reroll-btn").forEach(btn => {
    btn.addEventListener("click", async () => {
      const actorId = btn.dataset.actorId
      const actor = game.actors.get(actorId)
      if (!actor) {
        ui.notifications.warn(game.i18n.localize("MGNE.Notification.ActorNotFound"))
        return
      }

      const currentOmens = actor.system.omens?.current ?? 0
      if (currentOmens === 0) {
        ui.notifications.warn(game.i18n.localize("MGNE.Notification.NoOmensLeft"))
        return
      }

      // Save original state for rollback
      const originalOmens = currentOmens

      // Disable button and show loading state
      const originalInnerHTML = btn.innerHTML
      btn.disabled = true
      btn.innerHTML = '<i class="fa-solid fa-star"></i> ' + game.i18n.localize("MGNE.Common.Processing")

      try {
        // Spend the omen
        await actor.update({ "system.omens.current": Math.max(0, currentOmens - 1) })

        // Re-roll with the same parameters
        const abilityId = btn.dataset.abilityId
        const label = btn.dataset.label
        const baseDR = parseInt(btn.dataset.baseDr ?? "12", 10)
        const modifier = parseInt(btn.dataset.modifier ?? "0", 10)
        const rollType = btn.dataset.rollType ?? "check"
        const itemId = btn.dataset.itemId
        const item = itemId ? actor.items.get(itemId) : null

        await MGNERoll.promptCheck({
          actor,
          abilityId,
          label,
          baseDR,
          modifier,
          rollType,
          item,
        })
      } catch (error) {
        // Rollback omen spend on error
        const currentOmensAfterError = actor.system.omens?.current ?? 0
        if (currentOmensAfterError < originalOmens) {
          await actor.update({ "system.omens.current": originalOmens })
        }
        ui.notifications.error(game.i18n.localize("MGNE.Notification.RollError"))
        console.error("Omen re-roll failed:", error)
      } finally {
        // Restore button state
        btn.disabled = false
        btn.innerHTML = originalInnerHTML
      }
    })
  })

  root.querySelectorAll(".mgne-apply-damage-select").forEach(select => {
    const isAllowed = game.user.isGM || message.isAuthor
    if (!isAllowed) {
      select.closest(".chat-apply-actions")?.remove()
      return
    }

    const card = select.closest(".mgne-chat-card")
    const damageTotal = parseInt(card?.dataset.damageTotal ?? "0", 10) || 0
    const damageCritical = card?.dataset.damageCritical === "true"

    const tokens = canvas.scene?.tokens.contents ?? []
    for (const token of tokens) {
      if (!token.actor) continue
      const opt = document.createElement("option")
      opt.value = token.id
      opt.textContent = token.name
      select.appendChild(opt)
    }

    if (tokens.length === 0) {
      const opt = document.createElement("option")
      opt.disabled = true
      opt.textContent = game.i18n.localize("MGNE.Roll.NoTargetSelected")
      select.appendChild(opt)
    }

    select.addEventListener("change", async event => {
      const tokenId = event.target.value
      if (!tokenId) return
      const token = canvas.scene?.tokens.get(tokenId)
      const targetActor = token?.actor
      if (!targetActor) return
      select.value = ""

      let finalDamage = damageTotal
      const targetOmens = targetActor.system?.omens?.current ?? 0
      if (targetOmens > 0) {
        const spendOmen = await foundry.applications.api.DialogV2.wait({
          window: { title: game.i18n.localize("MGNE.RollDialog.OmenReduceTitle") },
          classes: ["mgne", "roll-dialog"],
          content: `<section class="mgne-roll-dialog"><p>${game.i18n.format("MGNE.RollDialog.OmenReducePrompt", { name: targetActor.name, omens: targetOmens })}</p></section>`,
          buttons: [
            { label: game.i18n.localize("MGNE.Common.No"), icon: "fa-solid fa-xmark", callback: () => false },
            { label: game.i18n.localize("MGNE.RollDialog.OmenReduceButton"), icon: "fa-solid fa-star", callback: () => true },
          ],
          rejectClose: false,
        })
        if (spendOmen) {
          const reduceRoll = await (new Roll("1d6")).evaluate()
          // Re-read omens after dialog to avoid overwriting concurrent changes
          const currentTargetOmens = targetActor.system?.omens?.current ?? 0
          await targetActor.update({ "system.omens.current": Math.max(0, currentTargetOmens - 1) })
          finalDamage = Math.max(0, damageTotal - reduceRoll.total)
          const reduceMsg = game.i18n.format("MGNE.Roll.OmenReducedDamage", {
            name: targetActor.name, reduced: reduceRoll.total, final: finalDamage,
          })
          await ChatMessage.create({
            speaker: ChatMessage.getSpeaker({ actor: targetActor }),
            rolls: [reduceRoll],
            content: `<article class="mgne-chat-card mode-check"><div class="chat-card-body"><p class="chat-special">${reduceMsg}</p></div></article>`,
          })
        }
      }

      await targetActor.applyDamage(finalDamage, { critical: damageCritical, chat: true })
    })
  })
})
