/**
 * 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/
 */

import { rollInitiativePC, rollInitiativeNPC } from "../ui/initiative.js"
import { ACTOR_TYPES } from "../config/constants.js"

/**
 * Custom Combat document for Chroniques de l'Étrange.
 *
 * The initiative wheel has 24 crans (positions). The character with the
 * highest initiative acts first (furthest counter-clockwise from reference).
 * After each action, their position advances clockwise by the action's cran cost
 * (initiative decreases, wrapping from 1 → 24).
 *
 * Sort order: descending by initiative (highest acts first).
 */
export class CDECombat extends Combat {

  /**
   * Override rollInitiative to open the PC or NPC initiative dialog
   * for each selected combatant, then sync the result to the Combatant document.
   */
  async rollInitiative(ids, options = {}) {
    const combatantIds = ids
      ? (typeof ids === "string" ? [ids] : ids)
      : this.combatants.map(c => c.id)
    for (const id of combatantIds) {
      const combatant = this.combatants.get(id)
      if (!combatant) continue
      const actor = combatant.actor
      if (!actor) continue

      if (actor.type === ACTOR_TYPES.character) {
        await rollInitiativePC(actor)
      } else {
        await rollInitiativeNPC(actor)
      }
      // combatant.initiative is synced by the updateActor hook in system.js
      // (triggered by actor.update inside rollInitiativePC/NPC)
    }
    return this
  }

  /**
   * Sort combatants: highest initiative first (furthest counter-clockwise = acts first).
   * Ties: PCs before NPCs; among PCs, by name; among NPCs, by name.
   * Calls super.setupTurns() first to ensure this.current is properly initialized.
   */
  setupTurns() {
    super.setupTurns()
    this.turns = this.turns.slice().sort((a, b) => {
      const ia = a.initiative ?? 0
      const ib = b.initiative ?? 0
      if (ia !== ib) return ib - ia // descending — highest acts first

      // Tie-break: PCs before NPCs
      const aIsPC = a.actor?.type === ACTOR_TYPES.character ? 1 : 0
      const bIsPC = b.actor?.type === ACTOR_TYPES.character ? 1 : 0
      if (aIsPC !== bIsPC) return bIsPC - aIsPC

      return (a.name ?? "").localeCompare(b.name ?? "")
    })
    return this.turns
  }
}

/**
 * Advance a combatant's wheel position by the given action cran cost.
 * Position wraps: after reaching 1, it continues from 24.
 *
 * @param {Combatant} combatant
 * @param {number}    cranCost
 */
export async function advanceCombatantPosition(combatant, cranCost) {
  const current  = combatant.initiative ?? combatant.actor?.system?.initiative ?? 1
  const newValue = ((current - cranCost - 1 + 48) % 24) + 1
  // Update combatant only; the updateCombatant hook in system.js syncs actor.initiative.
  await combatant.update({ initiative: newValue })
}
