/**
 * Lethal Fantasy RPG System
 * Author: LeRatierBretonnien/Uberwald
 */

import { SYSTEM } from "./module/config/system.mjs"

// Import modules
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 { LethalFantasyCombatTracker, LethalFantasyCombat } from "./module/applications/combat.mjs"
import { Macros } from "./module/macros.mjs"
import { setupTextEnrichers } from "./module/enrichers.mjs"
import LethalFantasyUtils, { log } from "./module/utils.mjs"

// Import chat reaction hooks (renderChatMessageHTML, preCreateChatMessage, defense/attack reactions, resource costing, auto-damage)
import "./module/hooks/chat-reaction.mjs"

Hooks.once("init", function () {
  globalThis.SYSTEM = SYSTEM
  globalThis.pendingDefenses = new Map()
  console.info("Lethal Fantasy RPG | Initializing System")
  console.info(SYSTEM.ASCII)

  game.settings.register(game.system.id, "debug", {
    name: "Debug logging",
    scope: "client",
    config: true,
    default: false,
    type: Boolean,
  })

  globalThis.lethalFantasy = game.system
  globalThis.log = log
  game.system.CONST = SYSTEM

  // Expose the system API
  game.system.api = {
    applications,
    models,
    documents,
  }

  CONFIG.ui.combat = LethalFantasyCombatTracker
  CONFIG.Combat.documentClass = LethalFantasyCombat;

  CONFIG.Actor.documentClass = documents.LethalFantasyActor
  CONFIG.Actor.dataModels = {
    character: models.LethalFantasyCharacter,
    monster: models.LethalFantasyMonster,
  }

  CONFIG.Item.documentClass = documents.LethalFantasyItem
  CONFIG.Item.dataModels = {
    skill: models.LethalFantasySkill,
    gift: models.LethalFantasyGift,
    weapon: models.LethalFantasyWeapon,
    armor: models.LethalFantasyArmor,
    shield: models.LethalFantasyShield,
    spell: models.LethalFantasySpell,
    vulnerability: models.LethalFantasyVulnerability,
    equipment: models.LethalFantasyEquipment,
    miracle: models.LethalFantasyMiracle
  }

  // Register sheet application classes (V2)
  foundry.documents.collections.Actors.registerSheet("lethalFantasy", applications.LethalFantasyCharacterSheet, { types: ["character"], makeDefault: true })
  foundry.documents.collections.Actors.registerSheet("lethalFantasy", applications.LethalFantasyMonsterSheet, { types: ["monster"], makeDefault: true })

  foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasySkillSheet, { types: ["skill"], makeDefault: true })
  foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyGiftSheet, { types: ["gift"], makeDefault: true })
  foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyVulnerabilitySheet, { types: ["vulnerability"], makeDefault: true })
  foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyWeaponSheet, { types: ["weapon"], makeDefault: true })
  foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasySpellSheet, { types: ["spell"], makeDefault: true })
  foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyArmorSheet, { types: ["armor"], makeDefault: true })
  foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyShieldSheet, { types: ["shield"], makeDefault: true })
  foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyEquipmentSheet, { types: ["equipment"], makeDefault: true })
  foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyMiracleSheet, { types: ["miracle"], makeDefault: true })

  // Other Document Configuration
  CONFIG.ChatMessage.documentClass = documents.LethalFantasyChatMessage

  // Dice system configuration
  CONFIG.Dice.rolls.push(documents.LethalFantasyRoll)

  // Activate socket handler
  game.socket.on(`system.${SYSTEM.id}`, LethalFantasyUtils.handleSocketEvent)

  setupTextEnrichers()
  LethalFantasyUtils.registerHandlebarsHelpers()
  LethalFantasyUtils.setHookListeners()

  console.info("LETHAL FANTASY | System Initialized")
})

/**
 * Perform one-time configuration of system configuration objects.f
 */
function preLocalizeConfig() {
  const localizeConfigObject = (obj, keys) => {
    for (let o of Object.values(obj)) {
      for (let k of keys) {
        o[k] = game.i18n.localize(o[k])
      }
    }
  }
}

Hooks.once("ready", async function () {
  console.info("LETHAL FANTASY | Ready")

  // Initialiser la table des résultats D30
  await documents.D30Roll.initialize()

  // Register Handlebars partials used by chat templates.
  // The object key is the partial ID referenced in templates (e.g., {{> chat/dice-breakdown}}),
  // the value is the file path. Using an array would register with the full path as the ID,
  // which does NOT match the template reference.
  await foundry.applications.handlebars.loadTemplates({
    "chat/dice-breakdown": "systems/fvtt-lethal-fantasy/templates/chat/_dice-breakdown.hbs"
  })

  // Saignement piloté par le combat tracker
  _registerBleedingHooks()

  _showUserGuide()

  /**
   *
   */
  async function _showUserGuide() {
    if (game.user.isGM) {
      const newVer = game.system.version
    }
  }
})

/**
 * Saignement piloté par le combat tracker.
 * Chaque round = 1 seconde → les acteurs qui saignent perdent 1 HP/blessure.
 * Hors combat, une notification prévient le MJ que des blessures saignent encore.
 */
function _registerBleedingHooks() {
  if (!game.user.isGM) return

  Hooks.on("combatRound", async (combat, previous, current) => {
    if (previous === current) return
    const processed = new Set()
    for (const combatant of combat.combatants) {
      const actor = combatant.actor
      if (!actor || processed.has(actor.id)) continue
      processed.add(actor.id)
      await _applyBleedingTick(actor)
    }
  })

  Hooks.on("combatEnd", async (combat) => {
    const bleeding = _findBleedingActors()
    if (bleeding.length) {
      ui.notifications.warn(
        game.i18n.format("LETHALFANTASY.Notifications.bleedingCombatEnd", {
          names: bleeding.map(a => a.name).join(", "),
        })
      )
    }
  })

  Hooks.on("combatStart", async (combat) => {
    const bleeding = _findBleedingActors()
    if (bleeding.length) {
      ui.notifications.warn(
        game.i18n.format("LETHALFANTASY.Notifications.bleedingCombatStart", {
          names: bleeding.map(a => a.name).join(", "),
        })
      )
    }
  })
}

/**
 * Appliquer 1 HP de dégât par blessure active, décrémenter la durée.
 * @param {import("foundry/common/documents.mjs").Actor} actor
 */
async function _applyBleedingTick(actor) {
  if (!actor?.system?.hp?.wounds) return
  const wounds = foundry.utils.duplicate(actor.system.hp.wounds)
  let hpLoss = 0
  let changed = false
  for (const wound of wounds) {
    if (wound.duration > 0 && wound.value > 0) {
      hpLoss += 1
      wound.duration -= 1
      if (wound.duration <= 0) {
        wound.value = 0
        wound.description = ""
      }
      changed = true
    }
  }
  if (!changed) return
  const currentHp = actor.system.hp.value ?? 0
  await actor.update({
    "system.hp.value": currentHp - hpLoss,
    "system.hp.wounds": wounds,
  })
}

/**
 * Retourne les acteurs (monde + tokens) qui ont des blessures actives.
 * @returns {import("foundry/common/documents.mjs").Actor[]}
 */
function _findBleedingActors() {
  const actors = []
  for (const actor of game.actors.values()) {
    if (actor?.system?.hp?.wounds?.some(w => w.duration > 0 && w.value > 0)) {
      actors.push(actor)
    }
  }
  for (const token of canvas.tokens?.placeables ?? []) {
    if (token.actor && !actors.includes(token.actor)) {
      if (token.actor?.system?.hp?.wounds?.some(w => w.duration > 0 && w.value > 0)) {
        actors.push(token.actor)
      }
    }
  }
  return actors
}

/**
 * Create a macro when dropping an entity on the hotbar
 * Item      - open roll dialog
 * Actor     - open actor sheet
 * Journal   - open journal sheet
 */
Hooks.on("hotbarDrop", (bar, data, slot) => {
  if (["Actor", "Item", "JournalEntry", "roll", "rollDamage", "rollAttack"].includes(data.type)) {
    Macros.createLethalFantasyMacro(data, slot);
    return false
  }
})

/* -------------------------------------------- */
/**
 * Inject the Lethal Fantasy dice tray into the chat sidebar.
 */
Hooks.on("renderChatLog", (_chatLog, html) => applications.injectDiceTray(_chatLog, html))
