import HamalronActorSheet from "./base-actor-sheet.mjs"
import { SYSTEM } from "../../config/system.mjs"
import HamalronUtils from "../../utils.mjs"

export default class HamalronPersonnageSheet extends HamalronActorSheet {
  /** @override */
  static DEFAULT_OPTIONS = {
    classes: ["character"],
    position: {
      width: 860,
      height: 620,
    },
    window: {
      contentClasses: ["character-content"],
    },
    actions: {
      createEquipment: HamalronPersonnageSheet.#onCreateEquipment,
      createArmor: HamalronPersonnageSheet.#onCreateArmor,
      createWeapon: HamalronPersonnageSheet.#onCreateWeapon,
      createSortilege: HamalronPersonnageSheet.#onCreateSortilege,
      openRecovery: HamalronPersonnageSheet.#onOpenRecovery,
      modifyResistance: HamalronPersonnageSheet.#onModifyResistance,
      removeWound: HamalronPersonnageSheet.#onRemoveWound,
      discardCard: HamalronPersonnageSheet.#onDiscardCard,
      rollCompetence: HamalronPersonnageSheet.#onRollCompetence,
      castSortilege: HamalronPersonnageSheet.#onCastSortilege,
      drawCard: HamalronPersonnageSheet.#onDrawCard,
      selectCard: HamalronPersonnageSheet.#onSelectCard,
      discardAndDraw: HamalronPersonnageSheet.#onDiscardAndDraw,
    },
  }

  /** @override */
  static PARTS = {
    main: {
      template: "systems/fvtt-hamalron/templates/personnage-main.hbs",
    },
    tabs: {
      template: "templates/generic/tab-navigation.hbs",
    },
    competences: {
      template: "systems/fvtt-hamalron/templates/personnage-status.hbs",
    },
    tarot: {
      template: "systems/fvtt-hamalron/templates/personnage-tarot.hbs",
    },
    sortileges: {
      template: "systems/fvtt-hamalron/templates/personnage-sortileges.hbs",
    },
    equipment: {
      template: "systems/fvtt-hamalron/templates/personnage-equipement.hbs",
    },
    biography: {
      template: "systems/fvtt-hamalron/templates/personnage-biographie.hbs",
    },
  }

  /** @override */
  tabGroups = {
    sheet: "competences",
  }

  /**
   * Prepare an array of form header tabs.
   * @returns {Record<string, Partial<ApplicationTab>>}
   */
  #getTabs() {
    const tabs = {
      competences: { id: "competences", group: "sheet", icon: "fa-solid fa-list-check", label: "HAMALRON.Label.competences" },
      tarot: { id: "tarot", group: "sheet", icon: "fa-solid fa-cards", label: "HAMALRON.Label.tarot" },
      sortileges: { id: "sortileges", group: "sheet", icon: "fa-solid fa-wand-magic-sparkles", label: "HAMALRON.Label.sortileges" },
      equipment: { id: "equipment", group: "sheet", icon: "fa-solid fa-shapes", label: "HAMALRON.Label.equipment" },
      biography: { id: "biography", group: "sheet", icon: "fa-solid fa-book", label: "HAMALRON.Label.biography" },
    }
    for (const v of Object.values(tabs)) {
      v.active = this.tabGroups[v.group] === v.id
      v.cssClass = v.active ? "active" : ""
    }
    return tabs
  }

  /** @override */
  async _prepareContext() {
    const context = await super._prepareContext()
    context.tabs = this.#getTabs()

    const doc = this.document

    return context
  }

  /** @override */
  async _preparePartContext(partId, context) {
    const doc = this.document
    context.systemFields = this.document.system.schema.fields
    switch (partId) {
      case "main":
        // Get peuple and faction items (only one of each allowed)
        context.peuple = doc.itemTypes.peuple?.[0] || null
        context.faction = doc.itemTypes.faction?.[0] || null
        context.isEditMode = this.isEditMode
        context.isPlayMode = this.isPlayMode
        break
      case "competences":
        context.tab = context.tabs.competences
        const allCompetences = doc.itemTypes.competence || []
        // Ajouter les données de niveau enrichies à chaque compétence
        allCompetences.forEach(c => {
          const niveauData = SYSTEM.NIVEAU_COMPETENCES[c.system.niveau]
          c.niveauName = niveauData?.name || c.system.niveau
          c.niveauModificateur = niveauData?.modificateur ?? 0
        })
        // Grouper les compétences par type et trier par nom dans chaque groupe
        context.competencesCommunes = allCompetences.filter(c => c.system.type === 'commune').sort((a, b) => a.name.localeCompare(b.name))
        context.competencesPeuple = allCompetences.filter(c => c.system.type === 'peuple').sort((a, b) => a.name.localeCompare(b.name))
        context.competencesFaction = allCompetences.filter(c => c.system.type === 'faction').sort((a, b) => a.name.localeCompare(b.name))
        break;
      case "sortileges":
        context.tab = context.tabs.sortileges
        context.sortileges = doc.itemTypes.sortilege || []
        context.sortileges.sort((a, b) => a.name.localeCompare(b.name))
        break
      case "equipment":
        context.tab = context.tabs.equipment
        context.weapons = doc.itemTypes.arme || []
        context.weapons.sort((a, b) => a.name.localeCompare(b.name))
        context.armors = doc.itemTypes.armure || []
        context.armors.sort((a, b) => a.name.localeCompare(b.name))
        context.equipments = doc.itemTypes.equipement || []
        context.equipments.sort((a, b) => a.name.localeCompare(b.name))
        break
      case "tarot":
        context.tab = context.tabs.tarot
        context.tarotCards = doc.itemTypes.tarot || []
        context.tarotCards.sort((a, b) => a.name.localeCompare(b.name))
        context.handLimit = 7
        context.handSize = context.tarotCards.length
        context.isOverLimit = context.handSize > context.handLimit
        context.canAddCard = context.handSize < context.handLimit
        for (const card of context.tarotCards) {
          card.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(card.system.description, { async: true })
          if (doc.system.cartesSucces && card.system.type !== "atout") {
            card.isSuccessCard = Object.keys(doc.system.cartesSucces).some(symbole => {
              const successCardData = doc.system.cartesSucces[symbole]
              return card.system.symbole === symbole &&
                String(card.system.valeur) === String(successCardData.value)
            })
          } else {
            card.isSuccessCard = false
          }
        }
        break
      case "biography":
        context.tab = context.tabs.biography
        context.enrichedHistorial = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.historial, { async: true })
        break
    }
    return context
  }


  static #onCreateEquipment(event, target) {
    this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newEquipment"), type: "equipement" }])
  }

  static #onCreateWeapon(event, target) {
    this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newWeapon"), type: "arme" }])
  }

  static #onCreateArmor(event, target) {
    this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newArmor"), type: "armure" }])
  }

  static #onCreateSortilege(event, target) {
    this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("HAMALRON.Label.newSortilege"), type: "sortilege" }])
  }

  static async #onOpenRecovery(event, target) {
    const { default: HamalronResistanceRecovery } = await import("../resistance-recovery.mjs")
    await HamalronResistanceRecovery.prompt(this.document)
  }

  static async #onModifyResistance(event, target) {
    const symbole = target.dataset.symbole
    const delta = Number.parseInt(target.dataset.delta)

    if (!symbole || isNaN(delta)) {
      console.warn(`HamalronPersonnageSheet: Invalid resistance modification parameters`)
      return
    }

    const resistance = this.document.system.resistances[symbole]
    if (!resistance) {
      console.warn(`HamalronPersonnageSheet: Resistance ${symbole} not found`)
      return
    }

    const newValue = Math.max(0, Math.min(resistance.max, resistance.value + delta))

    // Blessure incapacitante pour Épée (règle p.159)
    if (symbole === "epee" && delta < 0 && newValue < resistance.value && !this.document.system.blessureIncapacitante) {
      const choice = await foundry.applications.api.DialogV2.wait({
        window: { title: game.i18n.localize("HAMALRON.Wound.Title") },
        content: `<p>${game.i18n.localize("HAMALRON.Wound.Question")}</p>`,
        buttons: [
          { action: "wound", label: game.i18n.localize("HAMALRON.Wound.Take"), default: true, callback: () => "wound" },
          { action: "resist", label: game.i18n.localize("HAMALRON.Wound.Resist"), callback: () => "resist" },
        ],
        rejectClose: false,
      })
      if (choice === "wound") {
        await this.document.update({
          "system.blessureIncapacitante": true,
          "system.malusBlessure": -2,
        })
        ui.notifications.info(game.i18n.localize("HAMALRON.Wound.Active"))
        return
      }
    }

    await this.document.update({ [`system.resistances.${symbole}.value`]: newValue })
  }

  static async #onRemoveWound(event, target) {
    const confirmed = await foundry.applications.api.DialogV2.confirm({
      window: { title: game.i18n.localize("HAMALRON.Wound.Remove") },
      content: `<p>${game.i18n.localize("HAMALRON.Wound.RemoveConfirm")}</p>`,
      rejectClose: false,
      modal: true,
    })
    if (!confirmed) return
    await this.document.update({
      "system.blessureIncapacitante": false,
      "system.malusBlessure": 0,
    })
    ui.notifications.info(game.i18n.localize("HAMALRON.Wound.Healed"))
  }

  static async #onDiscardCard(event, target) {
    const itemId = $(event.target).data("item-id")
    const item = this.document.items.get(itemId)
    if (!item || item.type !== "tarot") {
      console.warn(`HamalronPersonnageSheet: Tarot card with ID ${itemId} not found`)
      return
    }

    // Supprimer la carte du personnage
    await item.delete()
    ui.notifications.info(game.i18n.localize("HAMALRON.Notifications.cardDiscarded") + item.name)
  }

  static async #onSelectCard(event, target) {
    const cardWrapper = $(target).closest(".tarot-card-wrapper")
    const wasSelected = cardWrapper.hasClass("selected")

    // Désélectionner toutes les cartes
    $(".tarot-card-wrapper").removeClass("selected")

    // Sélectionner la carte cliquée si elle n'était pas déjà sélectionnée
    if (!wasSelected) {
      cardWrapper.addClass("selected")
    }
  }

  static async #onDiscardAndDraw(event, target) {
    const itemId = $(target).data("item-id")
    const item = this.document.items.get(itemId)
    if (!item || item.type !== "tarot") {
      console.warn(`HamalronPersonnageSheet: Tarot card with ID ${itemId} not found`)
      return
    }

    // Dialog de confirmation
    const confirmed = await foundry.applications.api.DialogV2.confirm({
      window: {
        title: game.i18n.localize("HAMALRON.Dialog.discardCardTitle"),
      },
      content: `<p>${game.i18n.format("HAMALRON.Dialog.discardCardContent", { cardName: item.name })}</p>`,
      rejectClose: false,
      modal: true,
    })

    if (!confirmed) return

    // Récupérer le deck manager
    const module = await import("../tarot-deck-manager.mjs")
    const HamalronTarotDeckManager = module.default

    if (!HamalronTarotDeckManager._instance) {
      HamalronTarotDeckManager._instance = new HamalronTarotDeckManager()
    }

    const deckManager = HamalronTarotDeckManager._instance

    if (!deckManager) {
      ui.notifications.warn(game.i18n.localize("HAMALRON.Notifications.deckManagerNotAvailable"))
      return
    }

    // Ajouter la carte à la défausse
    deckManager.addToDiscard({
      id: item.id,
      name: item.name,
      img: item.img,
      symbole: item.system.symbole,
      valeur: item.system.valeur,
      type: item.system.type,
      description: item.system.description,
    })

    // Supprimer la carte du personnage
    await item.delete()

    // Tirer une nouvelle carte si le deck n'est pas vide
    if (deckManager.deck.length > 0) {
      const newCards = deckManager.drawCards(1)
      if (newCards.length > 0) {
        const newCard = newCards[0]

        // Cas spécial : Le Mat
        if (newCard.valeur === "lemat") {
          console.log("Le Mat drawn! Executing special rules...")
          const { default: HamalronTirageTarot } = await import("../../documents/tirage-tarot.mjs")
          await HamalronTirageTarot.handleLeMatEffect(this.document, deckManager)
        } else {
          const originalItem = await HamalronUtils.findTarotItem(newCard)
          if (originalItem) {
            await this.document.createEmbeddedDocuments("Item", [originalItem.toObject()])
            ui.notifications.info(game.i18n.localize("HAMALRON.Notifications.cardDiscardedAndDrawn") + newCard.name)
          }
        }
      }
    } else {
      ui.notifications.info(game.i18n.localize("HAMALRON.Notifications.cardDiscardedNoNew"))
    }

    await deckManager.saveDeckState()
    deckManager.render()
  }

  static async #onDrawCard(event, target) {
    const currentTarotCount = this.document.items.filter(i => i.type === "tarot").length

    // Vérifier que le joueur a moins de 7 cartes
    if (currentTarotCount >= 7) {
      ui.notifications.warn(game.i18n.localize("HAMALRON.Notifications.cannotDrawCard"))
      return
    }

    // Récupérer le deck manager singleton
    const module = await import("../tarot-deck-manager.mjs")
    const HamalronTarotDeckManager = module.default

    // Vérifier si l'instance existe, sinon la créer
    if (!HamalronTarotDeckManager._instance) {
      HamalronTarotDeckManager._instance = new HamalronTarotDeckManager()
    }

    const deckManager = HamalronTarotDeckManager._instance

    if (!deckManager) {
      ui.notifications.warn(game.i18n.localize("HAMALRON.Notifications.deckManagerNotAvailable"))
      return
    }

    if (deckManager.deck.length === 0) {
      ui.notifications.warn(game.i18n.localize("HAMALRON.Notifications.deckEmpty"))
      return
    }

    // Tirer une nouvelle carte
    const newCards = deckManager.drawCards(1)
    if (newCards.length > 0) {
      const newCard = newCards[0]

      // Cas spécial : Le Mat
      if (newCard.valeur === "lemat") {
        console.log("Le Mat drawn! Executing special rules...")
        const { default: HamalronTirageTarot } = await import("../../documents/tirage-tarot.mjs")
        await HamalronTirageTarot.handleLeMatEffect(this.document, deckManager)
      } else {
        const originalItem = await HamalronUtils.findTarotItem(newCard)
        if (originalItem) {
          await this.document.createEmbeddedDocuments("Item", [originalItem.toObject()])
          ui.notifications.info(game.i18n.localize("HAMALRON.Notifications.newCardDrawn") + newCard.name)
        }
      }
      await deckManager.saveDeckState()
      deckManager.render()
    }
  }

  static async #onCastSortilege(event, target) {
    const itemId = $(target).data("item-id")
    const item = this.document.items.get(itemId)
    if (!item || item.type !== "sortilege") {
      console.warn(`HamalronPersonnageSheet: Sortilege with ID ${itemId} not found`)
      return
    }
    const { default: HamalronSortilegeCasting } = await import("../sortilege-casting.mjs")
    await HamalronSortilegeCasting.prompt(item, this.document)
  }

  static async #onRollCompetence(event, target) {
    const itemId = $(target).data("item-id")
    const item = this.document.items.get(itemId)
    if (!item || item.type !== "competence") {
      console.warn(`HamalronPersonnageSheet: Competence with ID ${itemId} not found`)
      return
    }
    await this.document.system.roll("competence", item)
  }

  /**
   * Handles the roll action triggered by user interaction.
   *
   * @param {PointerEvent} event The event object representing the user interaction.
   * @param {HTMLElement} target The target element that triggered the roll.
   *
   * @returns {Promise<void>} A promise that resolves when the roll action is complete.
   *
   * @throws {Error} Throws an error if the roll type is not recognized.
   *
   * @description This method checks the current mode (edit or not) and determines the type of roll
   * (save, resource, or damage) based on the target element's data attributes. It retrieves the
   * corresponding value from the document's system and performs the roll.
   */
  async _onRoll(event, target) {
    const rollType = $(event.currentTarget).data("roll-type")
    let item
    let li
    let statKey
    switch (rollType) {
      case "stat":
        statKey = $(event.currentTarget).data("stat-id");
        item = this.actor.system?.stats?.[statKey];
        break
      case "weapon":
      case "damage":
        li = $(event.currentTarget).parents(".item");
        item = this.actor.items.get(li.data("item-id"));
        break
      default:
        throw new Error(`Unknown roll type ${rollType}`)
    }
    if (item) await this.document.system.roll(rollType, item)
  }

  async _onDrop(event) {
    if (!this.isEditable || !this.isEditMode) return
    const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event)

    // Handle different data types
    if (data.type === "Item") {
      const item = await fromUuid(data.uuid)
      if (item.type === "tarot") {
        // Check if a card with the same name already exists
        const existingCard = this.document.items.find(i => i.type === "tarot" && i.name === item.name)
        if (existingCard) {
          ui.notifications.warn(game.i18n.localize("HAMALRON.Notifications.tarotCardAlreadyExists") + item.name)
          return
        }

        const currentTarotCount = this.document.items.filter(i => i.type === "tarot").length

        if (currentTarotCount >= 7) {
          ui.notifications.warn(game.i18n.localize("HAMALRON.Notifications.tarotHandFull"))
          return
        }
      }
      return super._onDropItem(item)
    }

  }

}
