const { HandlebarsApplicationMixin } = foundry.applications.api

import { MaleficesUtility } from "../../malefices-utility.js"

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

  constructor(options = {}) {
    super(options)
    this.#dragDrop = this.#createDragDropHandlers()
    this._editScore = true
  }

  #dragDrop

  /** @override */
  static DEFAULT_OPTIONS = {
    classes: ["fvtt-malefices", "actor"],
    position: {
      width: 640,
      height: 680,
    },
    form: {
      submitOnChange: true,
    },
    window: {
      resizable: true,
    },
    dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
    actions: {
      editImage:      MaleficesActorSheet.#onEditImage,
      toggleSheet:    MaleficesActorSheet.#onToggleSheet,
      editItem:       MaleficesActorSheet.#onEditItem,
      deleteItem:     MaleficesActorSheet.#onDeleteItem,
      createItem:     MaleficesActorSheet.#onCreateItem,
      equipItem:      MaleficesActorSheet.#onEquipItem,
      modifyQuantity: MaleficesActorSheet.#onModifyQuantity,
      modifyAmmo:     MaleficesActorSheet.#onModifyAmmo,
      rollAttribut:   MaleficesActorSheet.#onRollAttribut,
      rollArme:       MaleficesActorSheet.#onRollArme,
      editSubActor:   MaleficesActorSheet.#onEditSubActor,
      deleteSubActor: MaleficesActorSheet.#onDeleteSubActor,
    },
  }

  /** @type {object} */
  tabGroups = { primary: "main" }

  /** @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,
      cssClass: this.isEditable ? "editable" : "locked",
      isGM: game.user.isGM,
      config: game.system.malefices.config,
      editScore: this._editScore,
    }
  }

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

    // Ignore Enter key in text inputs (not textarea)
    this.element.addEventListener('keydown', (e) => {
      if (e.key === 'Enter' && e.target.tagName !== 'TEXTAREA') e.preventDefault()
    })

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

    // Handle .update-field change events (legacy support)
    this.element.querySelectorAll('.update-field').forEach(el => {
      el.addEventListener('change', (ev) => {
        const fieldName = ev.currentTarget.dataset.fieldName
        const value = Number(ev.currentTarget.value)
        this.actor.update({ [fieldName]: value })
      })
    })
  }

  // #region Drag-and-Drop
  #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('.item')
    if (!li) return
    const itemId = li.dataset.itemId
    const item = this.actor.items.get(itemId)
    if (item) {
      event.dataTransfer.setData("text/plain", JSON.stringify({ type: "Item", uuid: item.uuid }))
    }
  }

  _onDragOver(event) {}

  async _onDrop(event) {
    const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event)
    if (data?.type === "Actor") {
      const actor = await fromUuid(data.uuid)
      if (actor) this.actor.addSubActor(actor.id)
    } else {
      super._onDrop(event)
    }
  }
  // #endregion

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

  static async #onToggleSheet(event, target) {
    this._editScore = !this._editScore
    this.render()
  }

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

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

  static async #onCreateItem(event, target) {
    const dataType = target.dataset.type
    this.actor.createEmbeddedDocuments('Item', [{ name: "NewItem", type: dataType }], { renderSheet: true })
  }

  static async #onEquipItem(event, target) {
    const li = target.closest(".item")
    const itemId = li?.dataset.itemId
    if (!itemId) return
    await this.actor.equipItem(itemId)
    this.render()
  }

  static async #onModifyQuantity(event, target) {
    const li = target.closest(".item")
    const itemId = li?.dataset.itemId
    if (!itemId) return
    const delta = parseInt(target.dataset.delta) || 0
    this.actor.incDecQuantity(itemId, delta)
  }

  static async #onModifyAmmo(event, target) {
    const li = target.closest(".item")
    const itemId = li?.dataset.itemId
    if (!itemId) return
    const delta = parseInt(target.dataset.delta) || 0
    this.actor.incDecAmmo(itemId, delta)
  }

  static async #onRollAttribut(event, target) {
    const attrKey = target.dataset.attrKey
    this.actor.rollAttribut(attrKey)
  }

  static async #onRollArme(event, target) {
    const armeId = target.dataset.armeId
    this.actor.rollArme(armeId)
  }

  static async #onEditSubActor(event, target) {
    const li = target.closest(".item")
    const actorId = li?.dataset.actorId
    if (!actorId) return
    game.actors.get(actorId)?.sheet.render(true)
  }

  static async #onDeleteSubActor(event, target) {
    const li = target.closest(".item")
    const actorId = li?.dataset.actorId
    if (!actorId) return
    this.actor.delSubActor(actorId)
  }
  // #endregion
}
