const { HandlebarsApplicationMixin } = foundry.applications.api

export default class HamalronTarotDeckManager extends HandlebarsApplicationMixin(foundry.applications.api.ApplicationV2) {
  constructor(options = {}) {
    super(options)
    this.deck = []
    this.discard = []
    this.loadDeckState()
  }

  /** @override */
  static DEFAULT_OPTIONS = {
    id: "tarot-deck-manager",
    classes: ["fvtt-hamalron", "tarot-deck-manager"],
    tag: "div",
    window: {
      title: "HAMALRON.TarotDeck.Title",
      icon: "fas fa-cards",
      resizable: true,
    },
    position: {
      width: 600,
      height: 700,
    },
    actions: {
      resetDeck: HamalronTarotDeckManager.#onResetDeck,
      drawCard: HamalronTarotDeckManager.#onDrawCard,
      drawMultiple: HamalronTarotDeckManager.#onDrawMultiple,
      shuffleDiscard: HamalronTarotDeckManager.#onShuffleDiscard,
      collectHands: HamalronTarotDeckManager.#onCollectHands,
      distributeCards: HamalronTarotDeckManager.#onDistributeCards,
      drawTension: HamalronTarotDeckManager.#onDrawTension,
      drawThreeTrumps: HamalronTarotDeckManager.#onDrawThreeTrumps,
      drawEightNumbered: HamalronTarotDeckManager.#onDrawEightNumbered,
      drawOneTrump: HamalronTarotDeckManager.#onDrawOneTrump,
    },
  }

  /** @override */
  static PARTS = {
    main: {
      template: "systems/fvtt-hamalron/templates/tarot-deck-manager.hbs",
    },
  }

  /**
   * Save the current deck state to settings
   */
  async saveDeckState() {
    const state = {
      deck: this.deck,
      discard: this.discard,
    }
    await game.settings.set("fvtt-hamalron", "tarotDeckState", state)
    console.log("Deck state saved:", state)
  }

  /**
   * Load the deck state from settings
   */
  loadDeckState() {
    const state = game.settings.get("fvtt-hamalron", "tarotDeckState")
    if (state && state.deck && state.deck.length > 0) {
      this.deck = state.deck
      this.discard = state.discard || []
      console.log("Deck state loaded:", state)
    } else {
      // Si aucun état sauvegardé, initialiser un nouveau deck
      this.resetDeck()
    }
  }

  /**
   * Reset the deck to a full tarot deck
   */
  resetDeck() {
    this.deck = []
    this.discard = []

    // Créer toutes les cartes du jeu de tarot
    const items = game.items.filter(i => i.type === "tarot")

    if (items.length > 0) {
      // Utiliser les items existants
      this.deck = items.map(item => ({
        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,
      }))
    } else {
      ui.notifications.warn("HAMALRON.TarotDeck.NoCardsFound", { localize: true })
    }

    // Mélanger le deck
    this.shuffleDeck()
    this.saveDeckState()
    this.render()
  }

  /**
   * Shuffle the deck using Fisher-Yates algorithm
   */
  shuffleDeck() {
    for (let i = this.deck.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [this.deck[i], this.deck[j]] = [this.deck[j], this.deck[i]]
    }
  }

  /**
   * Draw a card from the deck
   * @param {number} count - Number of cards to draw
   * @returns {Array} - Drawn cards
   */
  drawCards(count = 1) {
    if (this.deck.length === 0) {
      ui.notifications.warn("HAMALRON.TarotDeck.DeckEmpty", { localize: true })
      return []
    }

    const drawn = []
    for (let i = 0; i < count && this.deck.length > 0; i++) {
      const card = this.deck.shift()
      drawn.push(card)
    }

    return drawn
  }

  /**
   * Send drawn cards to chat
   * @param {Array} cards - Cards to send to chat
   */
  async sendCardsToChat(cards) {
    if (cards.length === 0) return

    const speaker = ChatMessage.getSpeaker({ alias: "Maître du Jeu" })

    for (const card of cards) {
      const content = await foundry.applications.handlebars.renderTemplate(
        "systems/fvtt-hamalron/templates/chat-tarot-draw.hbs",
        {
          card: card,
          symboleLabel: game.i18n.localize(`HAMALRON.Tarot.FIELDS.symbole.${card.symbole}`),
          valeurLabel: game.i18n.localize(`HAMALRON.Tarot.FIELDS.valeur.${card.valeur}`),
          typeLabel: game.i18n.localize(`HAMALRON.Tarot.FIELDS.type.${card.type}`),
        }
      )

      await ChatMessage.create({
        speaker: speaker,
        content: content,
        style: CONST.CHAT_MESSAGE_STYLES.OTHER,
      })
    }
  }

  /** @override */
  async _prepareContext(options) {
    const context = await super._prepareContext(options)

    context.deckCount = this.deck.length
    context.discardCount = this.discard.length
    context.totalCards = this.deck.length + this.discard.length
    context.hasCards = this.deck.length > 0
    context.hasDiscard = this.discard.length > 0

    return context
  }

  /**
   * Handle reset deck action
   * @param {Event} event
   * @param {HTMLElement} target
   */
  static async #onResetDeck(event, target) {
    const confirmed = await foundry.applications.api.DialogV2.confirm({
      window: { title: "HAMALRON.TarotDeck.ResetConfirm" },
      content: `<p>${game.i18n.localize("HAMALRON.TarotDeck.ResetWarning")}</p>`,
      rejectClose: false,
      modal: true,
    })

    if (confirmed) {
      this.resetDeck()
      ui.notifications.info("HAMALRON.TarotDeck.DeckReset", { localize: true })
    }
  }

  /**
   * Handle draw single card action
   * @param {Event} event
   * @param {HTMLElement} target
   */
  static async #onDrawCard(event, target) {
    const cards = this.drawCards(1)
    if (cards.length > 0) {
      await this.sendCardsToChat(cards)
      // Ajouter les cartes directement à la défausse
      cards.forEach(card => this.addToDiscard(card))
      this.saveDeckState()
      this.render()
    }
  }

  /**
   * Handle draw multiple cards action
   * @param {Event} event
   * @param {HTMLElement} target
   */
  static async #onDrawMultiple(event, target) {
    const count = parseInt(target.dataset.count || "1")
    const cards = this.drawCards(count)
    if (cards.length > 0) {
      await this.sendCardsToChat(cards)
      // Ajouter les cartes directement à la défausse
      cards.forEach(card => this.addToDiscard(card))
      this.saveDeckState()
      this.render()
    }
  }

  /**
   * Add a card to the discard pile
   * @param {Object} card - Card to add to discard
   */
  addToDiscard(card) {
    // Vérifier que la carte n'est pas déjà dans la défausse
    const cardExists = this.discard.some(c => c.id === card.id)
    if (!cardExists) {
      this.discard.push(card)
      this.saveDeckState()
      this.render()
    }
  }

  /**
   * Collect all tarot cards from player characters and return them to the deck
   * @param {Event} event
   * @param {HTMLElement} target
   */
  static async #onCollectHands(event, target) {
    const confirmed = await foundry.applications.api.DialogV2.confirm({
      window: { title: game.i18n.localize("HAMALRON.TarotDeck.CollectHandsConfirm") },
      content: `<p>${game.i18n.localize("HAMALRON.TarotDeck.CollectHandsWarning")}</p>`,
      rejectClose: false,
      modal: true,
    })

    if (!confirmed) return

    let totalCollected = 0

    // Récupérer tous les acteurs de type personnage (incluant tous, pas seulement ceux avec propriété joueur)
    const playerCharacters = game.actors.filter(a => a.type === "personnage")

    console.log("Found characters:", playerCharacters.length)

    // Collecter toutes les cartes de tarot de tous les personnages
    for (const actor of playerCharacters) {
      const tarotCards = actor.items.filter(i => i.type === "tarot")
      console.log(`Actor ${actor.name} has ${tarotCards.length} tarot cards`)

      if (tarotCards.length > 0) {
        // Supprimer les cartes de l'acteur
        const cardIds = tarotCards.map(c => c.id)
        console.log(`Deleting ${cardIds.length} cards from ${actor.name}`)
        await actor.deleteEmbeddedDocuments("Item", cardIds)
        console.log(`Deleted cards from ${actor.name}`)
        totalCollected += tarotCards.length
      }
    }

    // Réinitialiser le deck avec toutes les cartes de tarot disponibles
    this.deck = []
    this.discard = []

    const items = game.items.filter(i => i.type === "tarot")

    if (items.length > 0) {
      // Créer un Map pour éviter les doublons (utiliser l'ID unique)
      const uniqueCards = new Map()

      items.forEach(item => {
        const key = `${item.system.symbole}_${item.system.valeur}_${item.system.type}`
        if (!uniqueCards.has(key)) {
          uniqueCards.set(key, {
            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,
          })
        }
      })

      this.deck = Array.from(uniqueCards.values())
    }

    // Mélanger le deck
    this.shuffleDeck()

    this.saveDeckState()

    ui.notifications.info(
      game.i18n.format("HAMALRON.TarotDeck.HandsCollected", {
        collected: totalCollected,
        deckSize: this.deck.length
      })
    )

    this.render()
  }

  /**
   * Distribute 8 cards to all connected players (starting hand)
   * Excludes the Mat from distribution, then returns it to the deck and reshuffles
   * @param {Event} event
   * @param {HTMLElement} target
   */
  static async #onDistributeCards(event, target) {
    if (this.deck.length < 8) {
      ui.notifications.warn(game.i18n.localize("HAMALRON.TarotDeck.NotEnoughCards"))
      return
    }

    const confirmed = await foundry.applications.api.DialogV2.confirm({
      window: { title: game.i18n.localize("HAMALRON.TarotDeck.DistributeConfirm") },
      content: `<p>${game.i18n.localize("HAMALRON.TarotDeck.DistributeWarning")}</p>`,
      rejectClose: false,
      modal: true,
    })

    if (!confirmed) return

    let distributedCount = 0
    let playersCount = 0
    let matCard = null

    // Récupérer tous les utilisateurs connectés (sauf le GM)
    const connectedPlayers = game.users.filter(u => u.active && !u.isGM)

    for (const user of connectedPlayers) {
      // Trouver le personnage du joueur (premier actor de type personnage dont il est propriétaire)
      const playerCharacter = game.actors.find(a =>
        a.type === "personnage" &&
        a.testUserPermission(user, "OWNER")
      )

      if (playerCharacter) {
        // Tirer 8 cartes pour ce personnage (en ignorant le Mat)
        const cardsToDistribute = []
        let attempts = 0
        const maxAttempts = this.deck.length + 10 // Safety limit

        while (cardsToDistribute.length < 8 && this.deck.length > 0 && attempts < maxAttempts) {
          const card = this.deck.shift()
          attempts++

          // Si c'est le Mat, le mettre de côté
          if (card.valeur === "lemat") {
            matCard = card
            console.log("Le Mat trouvé et mis de côté pour être remis dans le deck après distribution")
            continue
          }

          cardsToDistribute.push(card)
        }

        // Créer les items sur l'acteur
        for (const card of cardsToDistribute) {
          const originalItem = game.items.get(card.id)
          if (originalItem) {
            await playerCharacter.createEmbeddedDocuments("Item", [originalItem.toObject()])
            distributedCount++
          }
        }

        playersCount++
      }
    }

    // Remettre le Mat dans le deck si il a été trouvé
    if (matCard) {
      this.deck.push(matCard)
      console.log("Le Mat a été remis dans le deck")
    }

    // Remélanger le deck restant
    this.shuffleDeck()
    console.log("Le deck restant a été remélangé")

    this.saveDeckState()

    ui.notifications.info(
      game.i18n.format("HAMALRON.TarotDeck.CardsDistributed", {
        cards: distributedCount,
        players: playersCount
      })
    )

    this.render()
  }

  /**
   * Draw 3 trumps (atouts only)
   * Cards are returned to deck and reshuffled after draw
   * @param {Event} event
   * @param {HTMLElement} target
   */
  static async #onDrawThreeTrumps(event, target) {
    const trumpCards = this.deck.filter(card => card.type === "atout")

    if (trumpCards.length < 3) {
      ui.notifications.warn(game.i18n.localize("HAMALRON.TarotDeck.NotEnoughTrumps"))
      return
    }

    // Tirer 3 atouts au hasard
    const drawnCards = []
    const availableTrumps = [...trumpCards]

    for (let i = 0; i < 3; i++) {
      const randomIndex = Math.floor(Math.random() * availableTrumps.length)
      const card = availableTrumps.splice(randomIndex, 1)[0]
      drawnCards.push(card)
    }

    // Envoyer au chat
    await this.sendCardsToChat(drawnCards)

    // Remélanger le deck (les cartes restent dedans)
    this.shuffleDeck()
    this.saveDeckState()
    this.render()

    ui.notifications.info(game.i18n.localize("HAMALRON.TarotDeck.ThreeTrumpsDrawn"))
  }

  /**
   * Draw 8 numbered cards (cards 1-10 from the 4 symbols)
   * Cards are returned to deck and reshuffled after draw
   * @param {Event} event
   * @param {HTMLElement} target
   */
  static async #onDrawEightNumbered(event, target) {
    const numberedCards = this.deck.filter(card => card.type === "numéro")

    if (numberedCards.length < 8) {
      ui.notifications.warn(game.i18n.localize("HAMALRON.TarotDeck.NotEnoughNumbered"))
      return
    }

    // Tirer 8 cartes numérotées au hasard
    const drawnCards = []
    const availableNumbered = [...numberedCards]

    for (let i = 0; i < 8; i++) {
      const randomIndex = Math.floor(Math.random() * availableNumbered.length)
      const card = availableNumbered.splice(randomIndex, 1)[0]
      drawnCards.push(card)
    }

    // Envoyer un résumé au chat
    await this.sendNumberedCardsSummaryToChat(drawnCards)

    // Remélanger le deck (les cartes restent dedans)
    this.shuffleDeck()
    this.saveDeckState()
    this.render()

    ui.notifications.info(game.i18n.localize("HAMALRON.TarotDeck.EightNumberedDrawn"))
  }

  /**
   * Draw 1 trump (atout only)
   * Card is returned to deck and reshuffled after draw
   * @param {Event} event
   * @param {HTMLElement} target
   */
  static async #onDrawOneTrump(event, target) {
    const trumpCards = this.deck.filter(card => card.type === "atout")

    if (trumpCards.length === 0) {
      ui.notifications.warn(game.i18n.localize("HAMALRON.TarotDeck.NoTrumpsAvailable"))
      return
    }

    // Tirer 1 atout au hasard
    const randomIndex = Math.floor(Math.random() * trumpCards.length)
    const card = trumpCards[randomIndex]

    // Envoyer au chat
    await this.sendCardsToChat([card])

    // Remélanger le deck (la carte reste dedans)
    this.shuffleDeck()
    this.saveDeckState()
    this.render()

    ui.notifications.info(game.i18n.localize("HAMALRON.TarotDeck.OneTrumpDrawn"))
  }

  /**
   * Shuffle discard pile back into deck
   * @param {Event} event
   * @param {HTMLElement} target
   */
  static async #onShuffleDiscard(event, target) {
    if (this.discard.length === 0) {
      ui.notifications.warn(game.i18n.localize("HAMALRON.TarotDeck.NoDiscard"))
      return
    }

    // Ajouter toutes les cartes de la défausse au deck
    this.deck.push(...this.discard)
    this.discard = []

    // Mélanger le deck
    this.shuffleDeck()

    this.saveDeckState()

    ui.notifications.info(game.i18n.localize("HAMALRON.TarotDeck.DiscardShuffled"))
    this.render()
  }

  /**
   * Handle draw tension action
   * @param {Event} event
   * @param {HTMLElement} target
   */
  static async #onDrawTension(event, target) {
    // Import system config
    const { DIFFICULTY_CHOICES } = await import('../config/system.mjs')

    // Créer les options de difficulté
    const difficulties = Object.entries(DIFFICULTY_CHOICES)
      .filter(([key]) => key !== 'soustension_oppose')
      .map(([key, value]) => ({
        value: key,
        label: value.label
      }))

    // Créer le contenu HTML du dialogue
    const selectOptions = difficulties.map(d =>
      `<option value="${d.value}">${d.label}</option>`
    ).join('')

    const content = `
      <div class="form-group">
        <label>${game.i18n.localize("HAMALRON.Label.difficulty")}</label>
        <select id="tension-difficulty" class="tension-select">
          ${selectOptions}
        </select>
      </div>
    `

    // Afficher le dialogue
    const result = await foundry.applications.api.DialogV2.wait({
      window: { title: game.i18n.localize("HAMALRON.TarotDeck.SelectDifficulty") },
      content: content,
      buttons: [
        {
          action: "draw",
          label: game.i18n.localize("HAMALRON.TarotDeck.DrawCard"),
          default: true,
          callback: (event, button, dialog) => {
            const select = button.form.elements["tension-difficulty"]
            return select.value
          }
        },
        {
          action: "cancel",
          label: game.i18n.localize("Cancel")
        }
      ],
      rejectClose: false,
      modal: true
    })

    if (!result) return

    // Tirer une carte
    const cards = this.drawCards(1)
    if (cards.length === 0) return

    const card = cards[0]
    const difficultyKey = result
    const difficulty = DIFFICULTY_CHOICES[difficultyKey]

    // Récupérer la valeur numérique de la carte
    const { TAROT_VALEURS } = await import('../config/system.mjs')
    const cardValue = TAROT_VALEURS[card.valeur]?.value || 0
    const tensionBonus = difficulty.soustension || 0
    const totalScore = cardValue + tensionBonus

    // Afficher dans le chat
    await this.sendTensionDrawToChat(card, difficulty, cardValue, tensionBonus, totalScore)

    // Ajouter à la défausse
    this.addToDiscard(card)
    this.saveDeckState()
    this.render()
  }

  /**
   * Send tension draw to chat
   * @param {Object} card - The drawn card
   * @param {Object} difficulty - The selected difficulty
   * @param {number} cardValue - Card numeric value
   * @param {number} tensionBonus - Tension modifier
   * @param {number} totalScore - Total score
   */
  async sendTensionDrawToChat(card, difficulty, cardValue, tensionBonus, totalScore) {
    const speaker = ChatMessage.getSpeaker({ alias: "Maître du Jeu" })

    const content = await foundry.applications.handlebars.renderTemplate(
      "systems/fvtt-hamalron/templates/chat-tarot-tension.hbs",
      {
        card: card,
        symboleLabel: game.i18n.localize(`HAMALRON.Tarot.FIELDS.symbole.${card.symbole}`),
        valeurLabel: game.i18n.localize(`HAMALRON.Tarot.FIELDS.valeur.${card.valeur}`),
        typeLabel: game.i18n.localize(`HAMALRON.Tarot.FIELDS.type.${card.type}`),
        difficulty: difficulty,
        cardValue: cardValue,
        tensionBonus: tensionBonus,
        totalScore: totalScore
      }
    )

    await ChatMessage.create({
      speaker: speaker,
      content: content,
      style: CONST.CHAT_MESSAGE_STYLES.OTHER,
    })
  }

  /**
   * Send numbered cards summary to chat
   * @param {Array} cards - Array of numbered cards
   */
  async sendNumberedCardsSummaryToChat(cards) {
    const speaker = ChatMessage.getSpeaker({ alias: "Maître du Jeu" })

    // Créer la liste des cartes
    const cardsList = cards.map(card => {
      const symboleLabel = game.i18n.localize(`HAMALRON.Tarot.FIELDS.symbole.${card.symbole}`)
      const valeurLabel = game.i18n.localize(`HAMALRON.Tarot.FIELDS.valeur.${card.valeur}`)
      return `
        <div class="tarot-card-summary-item">
          <img src="${card.img}" alt="${card.name}" title="${card.name}" />
          <span class="card-name">${valeurLabel} de ${symboleLabel}</span>
        </div>
      `
    }).join('')

    const content = `
      <div class="fvtt-hamalron chat-tarot-summary">
        <h3 class="tarot-summary-title">
          <i class="fas fa-hashtag"></i>
          ${game.i18n.localize("HAMALRON.TarotDeck.EightNumberedCardsDrawn")}
        </h3>
        <div class="tarot-cards-grid">
          ${cardsList}
        </div>
      </div>
    `

    await ChatMessage.create({
      speaker: speaker,
      content: content,
      style: CONST.CHAT_MESSAGE_STYLES.OTHER,
    })
  }

  /**
   * Open the Tarot Deck Manager application
   * @returns {HamalronTarotDeckManager}
   */
  static openManager() {
    if (!game.user.isGM) {
      ui.notifications.warn("HAMALRON.TarotDeck.GMOnly", { localize: true })
      return
    }

    // Singleton pattern - reuse existing instance or create new one
    if (!HamalronTarotDeckManager._instance) {
      HamalronTarotDeckManager._instance = new HamalronTarotDeckManager()
    }

    HamalronTarotDeckManager._instance.render(true, { focus: true })
    return HamalronTarotDeckManager._instance
  }
}
