/**
 * Manage Active Effect instances through an Actor or Item Sheet via effect control buttons.
 * @param {MouseEvent} event      The left-click event on the effect control
 * @param {Actor|Item} owner      The owning document which manages this effect
 */
export function onManageActiveEffect(event, owner) {
  event.preventDefault();
  const a = event.currentTarget;
  const li = a.closest('li');
  const effect = li.dataset.effectId
    ? owner.effects.get(li.dataset.effectId)
    : null;
  switch (a.dataset.action) {
    case 'create':
      return owner.createEmbeddedDocuments('ActiveEffect', [
        {
          name: game.i18n.format('DOCUMENT.New', {
            type: game.i18n.localize('DOCUMENT.ActiveEffect'),
          }),
          icon: 'icons/svg/aura.svg',
          origin: owner.uuid,
          'duration.rounds':
            li.dataset.effectType === 'temporary' ? 1 : undefined,
          disabled: li.dataset.effectType === 'inactive',
        },
      ]);
    case 'edit':
      return effect.sheet.render(true);
    case 'delete':
      return effect.delete();
    case 'toggle':
      return effect.update({ disabled: !effect.disabled });
  }
}

/**
 * Prepare the data structure for Active Effects which are currently embedded in an Actor or Item.
 * @param {ActiveEffect[]} effects    A collection or generator of Active Effect documents to prepare sheet data for
 * @return {object}                   Data for rendering
 */
export function prepareActiveEffectCategories(effects) {
  // Define effect header categories
  const categories = {
    temporary: {
      type: 'temporary',
      label: game.i18n.localize('MYRIAD_SYSTEM.Effect.Temporary'),
      effects: [],
    },
    passive: {
      type: 'passive',
      label: game.i18n.localize('MYRIAD_SYSTEM.Effect.Passive'),
      effects: [],
    },
    inactive: {
      type: 'inactive',
      label: game.i18n.localize('MYRIAD_SYSTEM.Effect.Inactive'),
      effects: [],
    },
  };

  // Iterate over active effects, classifying them into categories
  for (let e of effects) {
    if (e.disabled) categories.inactive.effects.push(e);
    else if (e.isTemporary) categories.temporary.effects.push(e);
    else categories.passive.effects.push(e);
  }
  return categories;
}

/**
 * Applique des dégâts temporaires à une caractéristique via le système d'ActiveEffects.
 * Cette fonction crée un effet temporaire qui réduit la valeur d'une caractéristique.
 * 
 * @param {Actor} actor              L'acteur auquel appliquer les dégâts
 * @param {string} characteristic    Le nom de la caractéristique (puissance, coordination, ingeniosite, perspicacite)
 * @param {number} amount            Le montant des dégâts (valeur positive)
 * @param {Object} [options]         Options additionnelles
 * @param {number} [options.duration] Durée en rounds (défaut: 10 rounds)
 * @param {string} [options.reason]   Raison des dégâts (pour le nom de l'effet)
 * @returns {Promise<ActiveEffect>}  L'effet créé
 */
export async function applyCharacteristicDamage(actor, characteristic, amount, options = {}) {
  // Vérifications de base
  if (!actor || !actor.isOwner) return null;
  if (!["puissance", "coordination", "ingeniosite", "perspicacite"].includes(characteristic)) {
    console.error(`Caractéristique invalide: ${characteristic}`);
    return null;
  }
  
  // S'assurer que le montant est positif (car c'est une réduction)
  amount = Math.abs(amount);
  if (amount <= 0) return null;
  
  // Préparer les options avec valeurs par défaut
  const duration = options.duration || 10; // 10 rounds par défaut
  const reason = options.reason || game.i18n.localize('MYRIAD_SYSTEM.Effect.TempDamage');
  
  // Créer l'effet
  const effectData = {
    name: `${game.i18n.format('MYRIAD_SYSTEM.Effect.CharacteristicDamage', {
      characteristic: game.i18n.localize(`MYRIAD_SYSTEM.Characteristic.${characteristic.capitalize()}`),
      amount: amount
    })} (${reason})`,
    icon: 'icons/svg/degen.svg',
    origin: actor.uuid,
    duration: {
      rounds: duration,
      startRound: game.combat?.round ?? 0,
      startTurn: game.combat?.turn ?? 0
    },
    changes: [
      {
        key: `system.characteristics.${characteristic}.value`,
        mode: CONST.ACTIVE_EFFECT_MODES.ADD,
        value: -amount
      }
    ],
    flags: {
      myriad: {
        effectType: "characteristicDamage",
        characteristic: characteristic,
        amount: amount
      }
    }
  };

  // Créer l'effet sur l'acteur
  const created = await actor.createEmbeddedDocuments('ActiveEffect', [effectData]);
  return created[0] || null;
}

/**
 * Vérifie et maintient les limites des caractéristiques en fonction des ActiveEffects appliqués.
 * Cette fonction s'assure qu'une caractéristique ne tombe pas en dessous de 0.
 * Elle est conçue pour être appelée lors de la préparation des données dérivées d'un acteur.
 * 
 * @param {Actor} actor L'acteur dont les caractéristiques doivent être vérifiées
 */
export function validateCharacteristicLimits(actor) {
  if (!actor?.system?.characteristics) return;
  
  for (const [key, char] of Object.entries(actor.system.characteristics)) {
    // S'assurer que la valeur ne descend pas sous 0
    if (char.value < 0) {
      actor.update({[`system.characteristics.${key}.value`]: 0});
    }
    
    // S'assurer que la valeur ne dépasse pas le maximum
    if (char.value > char.max) {
      actor.update({[`system.characteristics.${key}.value`]: char.max});
    }
  }
}

/**
 * Récupère la valeur effective d'une caractéristique en tenant compte des effets actifs.
 * Utile pour les jets de dés qui doivent utiliser la valeur réelle incluant tous les bonus/malus.
 * 
 * @param {Actor} actor L'acteur dont on veut récupérer la caractéristique
 * @param {string} characteristicName Le nom de la caractéristique
 * @returns {number} La valeur effective de la caractéristique
 */
export function getEffectiveCharacteristic(actor, characteristicName) {
  if (!actor?.system?.characteristics?.[characteristicName]) return 0;
  
  // Récupérer la valeur de base de la caractéristique
  const char = actor.system.characteristics[characteristicName];
  let value = char.value;
  
  // Les effets sont déjà appliqués à la valeur via le système d'ActiveEffect de Foundry
  // Mais on peut ajouter ici des modifications spécifiques au système Myriad si nécessaire
  
  // S'assurer que la valeur est dans les limites
  value = Math.max(0, Math.min(value, char.max));
  
  return value;
}

/**
 * Crée un effet d'amélioration temporaire pour une caractéristique.
 * 
 * @param {Actor} actor L'acteur à qui appliquer l'effet
 * @param {string} characteristic Le nom de la caractéristique à améliorer
 * @param {number} bonus Le bonus à appliquer (valeur positive)
 * @param {Object} options Options additionnelles
 * @param {number} [options.duration] Durée en rounds
 * @param {string} [options.reason] Raison du bonus
 * @returns {Promise<ActiveEffect>} L'effet créé
 */
export async function applyCharacteristicBonus(actor, characteristic, bonus, options = {}) {
  // Vérifications de base
  if (!actor || !actor.isOwner) return null;
  if (!["puissance", "coordination", "ingeniosite", "perspicacite"].includes(characteristic)) {
    console.error(`Caractéristique invalide: ${characteristic}`);
    return null;
  }
  
  // S'assurer que le bonus est positif
  bonus = Math.abs(bonus);
  if (bonus <= 0) return null;
  
  // Préparer les options avec valeurs par défaut
  const duration = options.duration || 10; // 10 rounds par défaut
  const reason = options.reason || game.i18n.localize('MYRIAD_SYSTEM.Effect.TempBonus');
  
  // Créer l'effet
  const effectData = {
    name: `${game.i18n.format('MYRIAD_SYSTEM.Effect.CharacteristicBonus', {
      characteristic: game.i18n.localize(`MYRIAD_SYSTEM.Characteristic.${characteristic.capitalize()}`),
      bonus: bonus
    })} (${reason})`,
    icon: 'icons/svg/boost.svg',
    origin: actor.uuid,
    duration: {
      rounds: duration,
      startRound: game.combat?.round ?? 0,
      startTurn: game.combat?.turn ?? 0
    },
    changes: [
      {
        key: `system.characteristics.${characteristic}.value`,
        mode: CONST.ACTIVE_EFFECT_MODES.ADD,
        value: bonus
      }
    ],
    flags: {
      myriad: {
        effectType: "characteristicBonus",
        characteristic: characteristic,
        amount: bonus
      }
    }
  };

  // Créer l'effet sur l'acteur
  const created = await actor.createEmbeddedDocuments('ActiveEffect', [effectData]);
  return created[0] || null;
}

/**
 * Supprime les effets de dégâts temporaires pour une caractéristique.
 * 
 * @param {Actor} actor L'acteur dont on veut supprimer l'effet
 * @param {string} characteristicKey Le nom de la caractéristique
 * @returns {Promise<ActiveEffect[]>} Les effets supprimés
 */
export async function removeTemporaryDamageEffect(actor, characteristicKey) {
  // Vérifications de base
  if (!actor || !actor.isOwner) return null;
  if (!["puissance", "coordination", "ingeniosite", "perspicacite"].includes(characteristicKey)) {
    console.error(`Caractéristique invalide: ${characteristicKey}`);
    return null;
  }
  
  // Trouver les effets de dégâts temporaires pour cette caractéristique
  const effectsToRemove = actor.effects.filter(e => 
    e.flags?.myriad?.effectType === "characteristicDamage" && 
    e.flags?.myriad?.characteristic === characteristicKey
  );
  
  if (effectsToRemove.length > 0) {
    return actor.deleteEmbeddedDocuments("ActiveEffect", effectsToRemove.map(e => e.id));
  }
  
  return null;
}

/**
 * Soigne une partie des dégâts temporaires d'une caractéristique.
 * Si le montant à soigner est égal ou supérieur aux dégâts, l'effet est supprimé.
 * Sinon, l'effet est mis à jour avec la valeur restante.
 * 
 * @param {Actor} actor L'acteur à soigner
 * @param {string} characteristicKey Le nom de la caractéristique
 * @param {number} healAmount Le montant à soigner (valeur positive)
 * @returns {Promise<ActiveEffect|null>} L'effet mis à jour ou null si supprimé
 */
export async function healTemporaryDamage(actor, characteristicKey, healAmount) {
  // Vérifications de base
  if (!actor || !actor.isOwner) return null;
  if (!["puissance", "coordination", "ingeniosite", "perspicacite"].includes(characteristicKey)) {
    console.error(`Caractéristique invalide: ${characteristicKey}`);
    return null;
  }
  
  // S'assurer que le montant est positif
  healAmount = Math.abs(healAmount);
  if (healAmount <= 0) return null;
  
  // Trouver l'effet de dégâts pour cette caractéristique
  const damageEffect = actor.effects.find(e => 
    e.flags?.myriad?.effectType === "characteristicDamage" && 
    e.flags?.myriad?.characteristic === characteristicKey
  );
  
  if (!damageEffect) return null;
  
  // Récupérer le montant actuel des dégâts
  const currentDamage = damageEffect.flags?.myriad?.amount || 0;
  
  // Calculer les dégâts restants après soin
  const remainingDamage = Math.max(0, currentDamage - healAmount);
  
  // Si tous les dégâts sont soignés, supprimer l'effet
  if (remainingDamage <= 0) {
    await actor.deleteEmbeddedDocuments("ActiveEffect", [damageEffect.id]);
    return null;
  }
  
  // Sinon, mettre à jour l'effet avec le montant restant
  const updated = await damageEffect.update({
    "flags.myriad.amount": remainingDamage,
    "changes": [
      {
        key: `system.characteristics.${characteristicKey}.value`,
        mode: CONST.ACTIVE_EFFECT_MODES.ADD,
        value: -remainingDamage
      }
    ]
  });
  
  return updated;
}
