/**
 * Donjon & Cie - Systeme FoundryVTT
 *
 * Donjon & Cie est un jeu de role edite par John Doe.
 * Ce systeme FoundryVTT est une implementation independante et n'est pas
 * affilie a John Doe.
 *
 * @author    LeRatierBretonnien
 * @copyright 2025–2026 LeRatierBretonnien
 * @license   CC BY-NC-SA 4.0 – https://creativecommons.org/licenses/by-nc-sa/4.0/
 */

const { HandlebarsApplicationMixin } = foundry.applications.api;

export default class DonjonEtCieActorSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) {
  static DEFAULT_OPTIONS = {
    classes: ["fvtt-donjon-et-cie", "sheet", "actor"],
    position: { width: 920, height: 820 },
    form: {
      submitOnChange: true,
      closeOnSubmit: false
    },
    window: {
      resizable: true
    },
    dragDrop: [{ dragSelector: ".item-list .item", dropSelector: ".item-dropzone" }],
    actions: {
      editImage: DonjonEtCieActorSheet.#onEditImage,
      setTab: DonjonEtCieActorSheet.#onSetTab,
      createItem: DonjonEtCieActorSheet.#onCreateItem,
      editItem: DonjonEtCieActorSheet.#onEditItem,
      deleteItem: DonjonEtCieActorSheet.#onDeleteItem,
      rollHitDice: DonjonEtCieActorSheet.#onRollHitDice,
      rollInitiative: DonjonEtCieActorSheet.#onRollInitiative,
      rollCharacteristic: DonjonEtCieActorSheet.#onRollCharacteristic,
      rollWeapon: DonjonEtCieActorSheet.#onRollWeapon,
      rollDamage: DonjonEtCieActorSheet.#onRollDamage,
      rollSpell: DonjonEtCieActorSheet.#onRollSpell,
      rollUsage: DonjonEtCieActorSheet.#onRollUsage,
      resetUsage: DonjonEtCieActorSheet.#onResetUsage,
      useFavorService: DonjonEtCieActorSheet.#onUseFavorService,
      postItem: DonjonEtCieActorSheet.#onPostItem,
      adjustCounter: DonjonEtCieActorSheet.#onAdjustCounter
    }
  };

  async _prepareContext() {
    const actor = this.document;
    return {
      actor,
      system: actor.system,
      source: actor.toObject(),
      config: game.system.donjonEtCie.config,
      characteristics: actor.getCharacteristicEntries(),
      sections: actor.getSectionData(),
      fields: actor.schema.fields,
      systemFields: actor.system.schema.fields,
      activeTab: this._activeTab ?? "combat"
    };
  }

  _onRender(context, options) {
    super._onRender(context, options);
    this.#fixWindowShell();
    this._applyActiveTab();
  }

  #fixWindowShell() {
    const app = this.element?.matches?.(".application") ? this.element : this.element?.closest(".application");
    const content = app?.querySelector(":scope > .window-content") ?? app?.querySelector(".window-content");
    const header = app?.querySelector(".window-header");

    if (app) {
      app.style.display = "flex";
      app.style.flexDirection = "column";
      app.style.paddingTop = "0";
      app.style.overflow = "hidden";
    }

    if (header) {
      header.style.width = "100%";
      header.style.flex = "0 0 auto";
      header.style.position = "relative";
      header.style.zIndex = "3";
    }

    if (content) {
      content.style.width = "100%";
      content.style.flex = "1 1 auto";
      content.style.minHeight = "0";
      content.style.overflowY = "auto";
      content.style.overflowX = "hidden";
    }
  }

  _canDragStart() {
    return this.isEditable;
  }

  _canDragDrop() {
    return this.isEditable;
  }

  _onDragStart(event) {
    const itemElement = event.currentTarget.closest(".item");
    if (!itemElement) return;

    const itemId = itemElement.dataset.itemId;
    const item = this.document.items.get(itemId);
    if (!item) return;

    event.dataTransfer.setData("text/plain", JSON.stringify({ type: "Item", uuid: item.uuid }));
  }

  _onDragOver(event) {
    const dropTarget = event.target.closest(".item-section");
    this.#setDropTarget(dropTarget);
  }

  async _onDrop(event) {
    this.#setDropTarget(null);
    return super._onDrop(event);
  }

  #setDropTarget(target) {
    this.element.querySelectorAll(".item-section.is-dragover").forEach((section) => section.classList.remove("is-dragover"));
    if (target instanceof HTMLElement) {
      target.classList.add("is-dragover");
    }
  }

  _applyActiveTab() {
    const activeTab = this._activeTab ?? "combat";
    this.element.querySelectorAll("[data-tab-button]").forEach((button) => {
      const isActive = button.dataset.tab === activeTab;
      button.classList.toggle("active", isActive);
      button.setAttribute("aria-pressed", isActive ? "true" : "false");
    });

    this.element.querySelectorAll("[data-tab-panel]").forEach((panel) => {
      const isActive = panel.dataset.tabPanel === activeTab;
      panel.classList.toggle("active", isActive);
      panel.toggleAttribute("hidden", !isActive);
    });
  }

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

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

  static async #onSetTab(event, target) {
    event.preventDefault();
    const tab = target.dataset.tab;
    if (!tab) return;
    this._activeTab = tab;
    this._applyActiveTab();
  }

  static async #onEditItem(event, target) {
    event.preventDefault();
    const item = this.document.items.get(target.closest("[data-item-id]")?.dataset.itemId);
    return item?.sheet.render(true);
  }

  static async #onDeleteItem(event, target) {
    event.preventDefault();
    const itemId = target.closest("[data-item-id]")?.dataset.itemId;
    if (!itemId) return;
    return this.document.deleteEmbeddedDocuments("Item", [itemId]);
  }

  static async #onRollCharacteristic(event, target) {
    event.preventDefault();
    return this.document.rollCharacteristic(target.dataset.characteristic);
  }

  static async #onRollInitiative(event) {
    event.preventDefault();
    return this.document.rollInitiative();
  }

  static async #onRollHitDice(event) {
    event.preventDefault();
    return this.document.rollHitDice();
  }

  static async #onRollWeapon(event, target) {
    event.preventDefault();
    return this.document.rollWeapon(target.closest("[data-item-id]")?.dataset.itemId);
  }

  static async #onRollDamage(event, target) {
    event.preventDefault();
    return this.document.rollDamage(target.closest("[data-item-id]")?.dataset.itemId);
  }

  static async #onRollSpell(event, target) {
    event.preventDefault();
    return this.document.rollSpell(target.closest("[data-item-id]")?.dataset.itemId);
  }

  static async #onRollUsage(event, target) {
    event.preventDefault();
    return this.document.rollUsage(target.closest("[data-item-id]")?.dataset.itemId);
  }

  static async #onResetUsage(event, target) {
    event.preventDefault();
    return this.document.resetUsage(target.closest("[data-item-id]")?.dataset.itemId);
  }

  static async #onUseFavorService(event, target) {
    event.preventDefault();
    return this.document.useFavorService(target.dataset.department);
  }

  static async #onPostItem(event, target) {
    event.preventDefault();
    const item = this.document.items.get(target.closest("[data-item-id]")?.dataset.itemId);
    return item?.postToChat();
  }

  static async #onAdjustCounter(event, target) {
    event.preventDefault();
    const path = target.dataset.path;
    const delta = Number(target.dataset.delta ?? 0);
    if (!path || Number.isNaN(delta)) return;
    return this.document.adjustNumericField(path, delta);
  }
}
