import EcrymeBaseActorSheet from "./base-actor-sheet.js"
import { EcrymeUtility } from "../../common/ecryme-utility.js"

/**
 * Actor sheet for PC and NPC types using Application V2.
 */
export default class EcrymeActorSheet extends EcrymeBaseActorSheet {

  #editScore = false

  /** @override */
  static DEFAULT_OPTIONS = {
    classes: ["pc-npc"],
    position: { width: 860, height: 680 },
    actions: {
      openAnnency:       EcrymeActorSheet.#onOpenAnnency,
      itemEdit:          EcrymeActorSheet.#onItemEdit,
      itemDelete:        EcrymeActorSheet.#onItemDelete,
      itemCreate:        EcrymeActorSheet.#onItemCreate,
      subactorEdit:      EcrymeActorSheet.#onSubactorEdit,
      subactorDelete:    EcrymeActorSheet.#onSubactorDelete,
      rollSkill:         EcrymeActorSheet.#onRollSkill,
      rollSpec:          EcrymeActorSheet.#onRollSpec,
      rollSkillConfront: EcrymeActorSheet.#onRollSkillConfront,
      rollCephaly:       EcrymeActorSheet.#onRollCephaly,
      rollWeaponConfront:EcrymeActorSheet.#onRollWeaponConfront,
      impactModify:      EcrymeActorSheet.#onImpactModify,
      rollWeapon:        EcrymeActorSheet.#onRollWeapon,
      lockUnlock:        EcrymeActorSheet.#onLockUnlock,
      equipItem:         EcrymeActorSheet.#onEquipItem,
      quantityMinus:     EcrymeActorSheet.#onQuantityMinus,
      quantityPlus:      EcrymeActorSheet.#onQuantityPlus,
      resetTranscendence:EcrymeActorSheet.#onResetTranscendence,
    },
  }

  /** @override */
  static PARTS = {
    header:     { template: "systems/fvtt-ecryme/templates/actors/partials/actor-header.hbs" },
    tabs:       { template: "templates/generic/tab-navigation.hbs" },
    skills:     { template: "systems/fvtt-ecryme/templates/actors/actor-skills.hbs" },
    traits:     { template: "systems/fvtt-ecryme/templates/actors/actor-traits.hbs" },
    combat:     { template: "systems/fvtt-ecryme/templates/actors/actor-combat.hbs" },
    cephaly:    { template: "systems/fvtt-ecryme/templates/actors/actor-cephaly.hbs" },
    equipements:{ template: "systems/fvtt-ecryme/templates/actors/actor-equipements.hbs" },
    biodata:    { template: "systems/fvtt-ecryme/templates/actors/actor-biodata.hbs" },
  }

  /** @override */
  tabGroups = { primary: "skills" }

  /** Build tabs, conditionally adding cephaly if the module is active */
  _getTabs() {
    const hasCephaly = EcrymeUtility.hasCephaly()
    const tabs = {
      skills:     { id: "skills",      group: "primary", label: "ECRY.ui.skills" },
      traits:     { id: "traits",      group: "primary", label: "ECRY.ui.traits" },
      combat:     { id: "combat",      group: "primary", label: "ECRY.ui.healthcombat" },
      equipements:{ id: "equipements", group: "primary", label: "ECRY.ui.equipment" },
      biodata:    { id: "biodata",     group: "primary", label: "ECRY.ui.bionotes" },
    }
    if (hasCephaly) {
      // Insert cephaly after combat, rebuilding the object to preserve insertion order
      const ordered = {}
      for (const [k, v] of Object.entries(tabs)) {
        ordered[k] = v
        if (k === "combat") ordered.cephaly = { id: "cephaly", group: "primary", label: "ECRY.ui.cephaly" }
      }
      for (const tab of Object.values(ordered)) {
        tab.active = this.tabGroups[tab.group] === tab.id
        tab.cssClass = tab.active ? "active" : ""
      }
      return ordered
    }
    for (const tab of Object.values(tabs)) {
      tab.active = this.tabGroups[tab.group] === tab.id
      tab.cssClass = tab.active ? "active" : ""
    }
    return tabs
  }

  /** @override */
  async _prepareContext() {
    const actor = this.document
    return {
      actor,
      system:       actor.system,
      source:       actor.toObject(),
      fields:       actor.schema.fields,
      systemFields: actor.system.schema.fields,
      type:         actor.type,
      img:          actor.img,
      name:         actor.name,
      isEditable:   this.isEditable,
      config:       game.ecryme.config,
      hasCephaly:   EcrymeUtility.hasCephaly(),
      hasBoheme:    EcrymeUtility.hasBoheme(),
      hasAmertume:  EcrymeUtility.hasAmertume(),
      skills:       actor.prepareSkills(),
      traits:       actor.getRollTraits(),
      ideal:        actor.getIdeal(),
      spleen:       actor.getSpleen(),
      weapons:      actor.getWeapons(),
      maneuvers:    actor.getManeuvers(),
      impactsMalus: actor.getImpactsMalus(),
      equipments:   actor.getEquipments(),
      cephalySkills:actor.getCephalySkills(),
      confrontations: actor.getConfrontations(),
      subActors:    actor.getSubActors(),
      annency:      actor.getAnnency(),
      owner:        this.document.isOwner,
      isGM:         game.user.isGM,
      editScore:    this.#editScore,
      tabs:         this._getTabs(),
    }
  }

  /** @override */
  async _preparePartContext(partId, context) {
    context = await super._preparePartContext(partId, context)
    switch (partId) {
      case "skills":
      case "traits":
      case "combat":
      case "cephaly":
      case "equipements":
        context.tab = context.tabs[partId] ?? { cssClass: "" }
        break
      case "biodata":
        context.tab = context.tabs.biodata
        context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(
          this.document.system.biodata.description, { async: true }
        )
        context.enrichedGmnotes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(
          this.document.system.biodata.gmnotes, { async: true }
        )
        break
    }
    return context
  }

  // #region Drag and Drop

  /** Handle incoming drops: Items from sidebar/compendium, Actors as subactors */
  async _onDrop(event) {
    const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event)
    if (!data?.type) return

    if (data.type === "Item") {
      const item = await fromUuid(data.uuid)
      if (!item) return
      await this.document.createEmbeddedDocuments("Item", [item.toObject()])
    } else if (data.type === "Actor") {
      const actor = fromUuidSync(data.uuid)
      if (actor) await this.actor.addSubActor(actor.id)
    }
  }

  /** Handle outgoing drag from embedded item rows */
  _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()))
  }

  // #endregion

  // #region Static Action Handlers

  static #onOpenAnnency(event, target) {
    const actorId = target.dataset.annencyId
    game.actors.get(actorId)?.sheet.render(true)
  }

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

  static async #onItemDelete(event, target) {
    const li = target.closest("[data-item-id]")
    EcrymeUtility.confirmDelete(this, $(li)).catch(() => {})
  }

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

  static #onSubactorEdit(event, target) {
    const li = target.closest("[data-actor-id]")
    game.actors.get(li?.dataset.actorId)?.sheet.render(true)
  }

  static #onSubactorDelete(event, target) {
    const li = target.closest("[data-actor-id]")
    this.actor.delSubActor(li?.dataset.actorId)
  }

  static #onRollSkill(event, target) {
    this.actor.rollSkill(target.dataset.categoryKey, target.dataset.skillKey)
  }

  static #onRollSpec(event, target) {
    this.actor.rollSpec(target.dataset.categoryKey, target.dataset.skillKey, target.dataset.specId)
  }

  static #onRollSkillConfront(event, target) {
    this.actor.rollSkillConfront(target.dataset.categoryKey, target.dataset.skillKey)
  }

  static #onRollCephaly(event, target) {
    this.actor.rollCephalySkillConfront(target.dataset.skillKey)
  }

  static #onRollWeaponConfront(event, target) {
    const li = target.closest("[data-item-id]")
    this.actor.rollWeaponConfront(li?.dataset.itemId)
  }

  static #onImpactModify(event, target) {
    this.actor.modifyImpact(
      target.dataset.impactType,
      target.dataset.impactLevel,
      Number(target.dataset.impactModifier)
    )
  }

  static #onRollWeapon(event, target) {
    this.actor.rollWeapon(target.dataset.armeId)
  }

  static #onLockUnlock(event, target) {
    this.#editScore = !this.#editScore
    this.render(true)
  }

  static #onEquipItem(event, target) {
    const li = target.closest("[data-item-id]")
    this.actor.equipItem(li?.dataset.itemId)
    this.render(true)
  }

  static #onQuantityMinus(event, target) {
    const li = target.closest("[data-item-id]")
    this.actor.incDecQuantity(li?.dataset.itemId, -1)
  }

  static #onQuantityPlus(event, target) {
    const li = target.closest("[data-item-id]")
    this.actor.incDecQuantity(li?.dataset.itemId, +1)
  }

  static async #onResetTranscendence(event, target) {
    await this.actor.resetSkillPool()
    this.render(true)
  }

  // #endregion
}
