const { HandlebarsApplicationMixin } = foundry.applications.api;

import { MournbladeCYD2Utility } from "../../mournblade-cyd2-utility.js";

export default class MournbladeCYD2ActorSheetV2 extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) {

  static SHEET_MODES = { EDIT: 0, PLAY: 1 };

  constructor(options = {}) {
    super(options);
    this.#dragDrop = this.#createDragDropHandlers();
    this._sheetMode = this.constructor.SHEET_MODES.PLAY;
  }

  #dragDrop;

  /** @override */
  static DEFAULT_OPTIONS = {
    classes: ["fvtt-mournblade-cyd-2-0", "sheet", "actor"],
    position: {
      width: 750,
      height: 820,
    },
    form: {
      submitOnChange: true,
      closeOnSubmit: false,
    },
    window: {
      resizable: true,
    },
    tabs: [
      {
        navSelector: 'nav[data-group="primary"]',
        contentSelector: "section.sheet-body",
        initial: "stats",
      },
    ],
    dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
    actions: {
      editImage: MournbladeCYD2ActorSheetV2.#onEditImage,
      toggleSheet: MournbladeCYD2ActorSheetV2.#onToggleSheet,
      editItem: MournbladeCYD2ActorSheetV2.#onEditItem,
      deleteItem: MournbladeCYD2ActorSheetV2.#onDeleteItem,
      createItem: MournbladeCYD2ActorSheetV2.#onCreateItem,
      equipItem: MournbladeCYD2ActorSheetV2.#onEquipItem,
      modifyQuantity: MournbladeCYD2ActorSheetV2.#onModifyQuantity,
      modifyAdversite: MournbladeCYD2ActorSheetV2.#onModifyAdversite,
      modifySante: MournbladeCYD2ActorSheetV2.#onModifySante,
      modifyAme: MournbladeCYD2ActorSheetV2.#onModifyAme,
      rollAttribut: MournbladeCYD2ActorSheetV2.#onRollAttribut,
      rollCompetence: MournbladeCYD2ActorSheetV2.#onRollCompetence,
      rollRune: MournbladeCYD2ActorSheetV2.#onRollRune,
      rollArmeOffensif: MournbladeCYD2ActorSheetV2.#onRollArmeOffensif,
      rollArmeSpecial: MournbladeCYD2ActorSheetV2.#onRollArmeSpecial,
      rollArmeDegats: MournbladeCYD2ActorSheetV2.#onRollArmeDegats,
      rollAssommer: MournbladeCYD2ActorSheetV2.#onRollAssommer,
      rollCoupBas: MournbladeCYD2ActorSheetV2.#onRollCoupBas,
      rollImmobiliser: MournbladeCYD2ActorSheetV2.#onRollImmobiliser,
      rollRepousser: MournbladeCYD2ActorSheetV2.#onRollRepousser,
      rollDesengager: MournbladeCYD2ActorSheetV2.#onRollDesengager,
      rollInitiative: MournbladeCYD2ActorSheetV2.#onRollInitiative,
      rollFuir: MournbladeCYD2ActorSheetV2.#onRollFuir,
      // Actions pour les ActiveEffects
      createEffect: MournbladeCYD2ActorSheetV2.#onCreateEffect,
      editEffect: MournbladeCYD2ActorSheetV2.#onEditEffect,
      deleteEffect: MournbladeCYD2ActorSheetV2.#onDeleteEffect,
      toggleEffect: MournbladeCYD2ActorSheetV2.#onToggleEffect,
      applyEffect: MournbladeCYD2ActorSheetV2.#onApplyEffect,
    },
  };

  get isPlayMode() {
    if (this._sheetMode === undefined) this._sheetMode = this.constructor.SHEET_MODES.PLAY;
    return this._sheetMode === this.constructor.SHEET_MODES.PLAY;
  }

  get isEditMode() {
    if (this._sheetMode === undefined) this._sheetMode = this.constructor.SHEET_MODES.PLAY;
    return this._sheetMode === this.constructor.SHEET_MODES.EDIT;
  }

  tabGroups = { primary: "stats" };

  /** @override */
  async _prepareContext() {
    const actor = this.document;
    return {
      actor,
      system: actor.system,
      source: actor.toObject(),
      fields: actor.schema.fields,
      systemFields: actor.system.schema.fields,
      isEditable: this.isEditable,
      isEditMode: this.isEditMode,
      isPlayMode: this.isPlayMode,
      isGM: game.user.isGM,
      config: game.system.mournbladecyd2.config,
      enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(
        actor.system.biodata?.description || "", { async: true }
      ),
      enrichedHabitat: await foundry.applications.ux.TextEditor.implementation.enrichHTML(
        actor.system.biodata?.habitat || "", { async: true }
      ),
    };
  }

  /** @override */
  _onRender(context, options) {
    super._onRender(context, options);
    this.#dragDrop.forEach((d) => d.bind(this.element));

    this.element.querySelectorAll('.edit-item-data').forEach(element => {
      element.addEventListener('change', async (event) => {
        const target = event.currentTarget;
        const itemElement = target.closest('[data-item-id]');
        if (!itemElement) return;
        const itemId = itemElement.dataset.itemId;
        const itemField = target.dataset.itemField;
        const dataType = target.dataset.dtype;
        const value = dataType === "Number" ? Number(target.value) : target.value;
        const item = this.document.items.get(itemId);
        if (item) await item.update({ [`system.${itemField}`]: value });
      });
    });

    // Tab navigation
    const nav = this.element.querySelector('nav.tabs[data-group]');
    if (nav) {
      const group = nav.dataset.group;
      const activeTab = this.tabGroups[group] || "stats";
      nav.querySelectorAll('[data-tab]').forEach(link => {
        const tab = link.dataset.tab;
        link.classList.toggle('active', tab === activeTab);
        link.addEventListener('click', (event) => {
          event.preventDefault();
          this.tabGroups[group] = tab;
          this.render();
        });
      });
      this.element.querySelectorAll(`[data-group="${group}"][data-tab]`).forEach(content => {
        content.classList.toggle('active', content.dataset.tab === activeTab);
      });
    }
  }

  #createDragDropHandlers() {
    return this.options.dragDrop.map(d => {
      d.permissions = {
        dragstart: this._canDragStart.bind(this),
        drop: this._canDragDrop.bind(this)
      };
      d.callbacks = {
        dragstart: this._onDragStart.bind(this),
        dragover: this._onDragOver.bind(this),
        drop: this._onDrop.bind(this)
      };
      return new foundry.applications.ux.DragDrop.implementation(d);
    });
  }

  _canDragStart(selector) { return this.isEditable; }
  _canDragDrop(selector) { return this.isEditable; }

  _onDragStart(event) {
    const li = event.currentTarget.closest("[data-item-id]");
    if (!li) return;
    const item = this.document.items.get(li.dataset.itemId);
    if (!item) return;
    event.dataTransfer.setData("text/plain", JSON.stringify(item.toDragData()));
  }

  _onDragOver(event) { event.preventDefault(); }

  async _onDrop(event) {
    const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
    if (data?.type === "Item") return this._onDropItem(event, data);
    if (data?.type === "Actor") return this._onDropActor(event, data);
  }

  async _onDropItem(event, data) {
    if (!this.document.isOwner) return;
    const item = await Item.fromDropData(data);
    if (!item) return;
    if (this.document.uuid === item.parent?.uuid) return;
    await this.document.createEmbeddedDocuments("Item", [item.toObject()]);
    this.render();
  }

  async _onDropActor(event, data) {}

  // #region Actions

  static async #onEditImage(event) {
    const fp = new FilePicker({
      type: "image",
      current: this.document.img,
      callback: (path) => this.document.update({ img: path })
    });
    fp.browse();
  }

  static #onToggleSheet(event) {
    this._sheetMode = this.isEditMode
      ? this.constructor.SHEET_MODES.PLAY
      : this.constructor.SHEET_MODES.EDIT;
    this.render();
  }

  static async #onEditItem(event, target) {
    const li = target.closest(".item");
    const item = this.document.items.get(li?.dataset.itemId);
    item?.sheet.render(true);
  }

  static async #onDeleteItem(event, target) {
    const li = target.closest(".item");
    await MournbladeCYD2Utility.confirmDelete(this, li);
  }

  static async #onCreateItem(event, target) {
    const itemType = target.dataset.type;
    await this.document.createEmbeddedDocuments("Item", [{ name: `Nouveau ${itemType}`, type: itemType }], { renderSheet: true });
  }

  static async #onEquipItem(event, target) {
    const li = target.closest(".item");
    const item = this.document.items.get(li?.dataset.itemId);
    if (item) await item.update({ "system.equipped": !item.system.equipped });
  }

  static async #onModifyQuantity(event, target) {
    const li = target.closest('[data-item-id]');
    const item = this.document.items.get(li?.dataset.itemId);
    const value = Number.parseInt(target.dataset.quantiteValue);
    if (item) {
      const newQty = Math.max(0, (item.system.quantite || 0) + value);
      await item.update({ "system.quantite": newQty });
    }
  }

  static async #onModifyAdversite(event, target) {
    const li = target.closest('[data-adversite]');
    const adversiteKey = li?.dataset.adversite;
    if (!adversiteKey) return;
    const value = Number.parseInt(target.dataset.adversiteValue);
    const current = this.document.system.adversite[adversiteKey] || 0;
    await this.document.update({ [`system.adversite.${adversiteKey}`]: Math.max(0, current + value) });
  }

  static async #onModifySante(event, target) {
    const type = target.dataset.type;
    const value = Number.parseInt(target.dataset.value);
    const current = this.document.system.sante[type] || 0;
    await this.document.update({ [`system.sante.${type}`]: Math.max(0, current + value) });
  }

  static async #onModifyAme(event, target) {
    const value = Number.parseInt(target.dataset.value);
    const current = this.document.system.ame.nbame || 0;
    await this.document.update({ "system.ame.nbame": Math.max(0, current + value) });
  }

  static async #onRollAttribut(event, target) {
    await this.document.rollAttribut(target.dataset.attrKey);
  }

  static async #onRollCompetence(event, target) {
    const li = target.closest('[data-item-id]');
    await this.document.rollCompetence(target.dataset.attrKey, li?.dataset.itemId);
  }

  static async #onRollRune(event, target) {
    const li = target.closest('[data-item-id]');
    await this.document.rollRune(li?.dataset.itemId);
  }

  static async #onRollArmeOffensif(event, target) {
    const li = target.closest('[data-item-id]');
    await this.document.rollArmeOffensif(target.dataset.armeId ?? li?.dataset.itemId);
  }

  static async #onRollArmeSpecial(event, target) {
    const li = target.closest('[data-item-id]');
    await this.document.rollArmeSpecial(target.dataset.armeId ?? li?.dataset.itemId);
  }

  static async #onRollArmeDegats(event, target) {
    const li = target.closest('[data-item-id]');
    await this.document.rollArmeDegats(target.dataset.armeId ?? li?.dataset.itemId);
  }

  static async #onRollAssommer(event, target) {
    await this.document.rollAssommer();
  }

  static async #onRollCoupBas(event, target) {
    await this.document.rollCoupBas();
  }

  static async #onRollImmobiliser(event, target) {
    await this.document.rollImmobiliser();
  }

  static async #onRollRepousser(event, target) {
    await this.document.rollRepousser();
  }

  static async #onRollDesengager(event, target) {
    await this.document.rollDesengager();
  }

  static async #onRollInitiative(event, target) {
    await this.document.rollAttribut("adr", true);
  }

  static async #onRollFuir(event, target) {
    await this.document.rollFuir();
  }

  // #region ActiveEffects Management

  /**
   * Crée un nouvel effet actif
   * @param {Event} event - Événement
   * @param {HTMLElement} target - Éléments cible
   * @private
   */
  static async #onCreateEffect(event, target) {
    event.preventDefault();
    if (!this.isEditable || !this.document) return;
    
    try {
      // Créer les données par défaut pour un nouvel effet
      const defaultEffectData = {
        name: game.i18n.localize("EFFECT.new") || "Nouvel Effet",
        icon: "systems/fvtt-mournblade-cyd-2-0/assets/icons/capacite.webp",
        description: "",
        changes: [],
        disabled: false,
        duration: {},
        origin: this.document.uuid,
        tint: "",
        transfer: true,
        flags: {}
      };
      
      // Créer directement l'effet actif sur l'acteur
      const [effect] = await this.document.createEmbeddedDocuments("ActiveEffect", [defaultEffectData]);
      
      if (effect) {
        // Ouvrir la feuille d'édition de l'effet
        effect.sheet.render(true);
      }
    } catch (error) {
      console.error("MournbladeCYD2 | Failed to create effect:", error);
      ui.notifications.error(
        game.i18n.localize("EFFECT.createError") || 
        "Erreur lors de la création de l'effet"
      );
    }
  }

  /**
   * Édite un effet actif existant
   * @param {Event} event - Événement
   * @param {HTMLElement} target - Éléments cible
   * @private
   */
  static async #onEditEffect(event, target) {
    event.preventDefault();
    if (!this.isEditable || !this.document) return;
    
    const effectId = target?.dataset?.effectId;
    if (!effectId) return;
    
    const effect = this.document.effects.get(effectId);
    if (effect) {
      // Ouvrir la sheet de l'effet pour édition
      effect.sheet.render(true);
    }
  }

  /**
   * Supprime un effet actif
   * @param {Event} event - Événement
   * @param {HTMLElement} target - Éléments cible
   * @private
   */
  static async #onDeleteEffect(event, target) {
    event.preventDefault();
    if (!this.isEditable || !this.document) return;
    
    const effectId = target?.dataset?.effectId;
    if (!effectId) return;
    
    const effect = this.document.effects.get(effectId);
    if (effect) {
      const effectName = effect.name;
      const confirmed = await foundry.applications.api.DialogV2.confirm({
        title: game.i18n.localize("EFFECT.deleteConfirm") || "Supprimer l'effet",
        content: game.i18n.localize("EFFECT.deleteConfirmText", {name: effectName}) || 
                `Êtes-vous sûr de vouloir supprimer l'effet "${effectName}" ?`
      });
      
      if (confirmed) {
        try {
          await this.document.deleteEmbeddedDocuments("ActiveEffect", [effectId]);
        } catch (error) {
          console.error("MournbladeCYD2 | Failed to delete effect:", error);
          ui.notifications.error(
            game.i18n.localize("EFFECT.deleteError") || 
            "Erreur lors de la suppression de l'effet"
          );
        }
      }
    }
  }

  /**
   * Toggle l'état actif/désactivé d'un effet
   * @param {Event} event - Événement
   * @param {HTMLElement} target - Éléments cible
   * @private
   */
  static async #onToggleEffect(event, target) {
    event.preventDefault();
    if (!this.isEditable || !this.document) return;
    
    const effectId = target?.dataset?.effectId;
    if (!effectId) return;
    
    const effect = this.document.effects.get(effectId);
    if (effect) {
      try {
        await effect.update({ disabled: !effect.disabled });
      } catch (error) {
        console.error("MournbladeCYD2 | Failed to toggle effect:", error);
        ui.notifications.error(
          game.i18n.localize("EFFECT.toggleError") || 
          "Erreur lors du basculement de l'effet"
        );
      }
    }
  }

  /**
   * Applique un effet à partir d'un item
   * @param {Event} event - Événement
   * @param {HTMLElement} target - Éléments cible
   * @private
   */
  static async #onApplyEffect(event, target) {
    event.preventDefault();
    const effectId = target?.dataset?.effectId;
    if (!effectId) return;
    
    const effect = this.document.effects.get(effectId);
    if (effect) {
      await effect.apply();
    }
  }

  // #endregion
}
