/**
 * Donjon & Cie - Systeme FoundryVTT
 *
 * Fenêtre de dialogue pour afficher les employés (PJ)
 * Structure : 2 onglets racine (Employés / Clients),
 * avec sous-onglets par PC ou par client.
 *
 * @author    LeRatierBretonnien
 * @copyright 2025–2026 LeRatierBretonnien
 * @license   CC BY-NC-SA 4.0
 */

import { DonjonEtCieUtility } from "../donjon-et-cie-utility.mjs";
import { DONJON_ET_CIE } from "../donjon-et-cie-config.mjs";

export class DonjonEtCieEmployesDialog {
  /**
   * Ouvre la fenêtre des employés
   */
  static async open() {
    const pcs = this.#getPlayerCharacters();
    const clientTokens = this.#getClients();
    const characteristicKeys = this.#getCharacteristicKeys();
    
    const pcsData = await Promise.all(
      pcs.map(async (pc) => this.#preparePcData(pc, characteristicKeys))
    );
    
    const templateContext = {
      pcs: pcsData,
      clients: clientTokens.map(t => this.#prepareClientData(t)),
      characteristicKeys
    };

    const content = await foundry.applications.handlebars.renderTemplate(
      "systems/fvtt-donjon-et-cie/templates/dialogs/employes-dialog.hbs",
      templateContext
    );

    return foundry.applications.api.DialogV2.wait({
      window: {
        title: "Employés",
        icon: "fa-solid fa-hard-hat"
      },
      classes: ["fvtt-donjon-et-cie", "dnc-employes-dialog-wrapper"],
      content,
      modal: false,
      buttons: [
        {
          action: "close",
          label: "Fermer",
          icon: "fa-solid fa-xmark",
          callback: () => true
        }
      ],
      rejectClose: false,
      render: (event, dialog) => this.#setupTabs(dialog)
    });
  }

  /**
   * Récupère les personnages joueurs (employés)
   */
  static #getPlayerCharacters() {
    return game.actors.filter(a => a.type === "character" || a.hasPlayerOwner);
  }

  /**
   * Récupère les PNJ clients de la scène courante (retourne les TokenDocuments)
   */
  static #getClients() {
    const scene = canvas?.scene ?? game.scenes?.current;
    if (!scene) return [];
    
    return scene.tokens.filter(token => {
      const actor = token.actor;
      return actor && 
             !actor.hasPlayerOwner && 
             actor.type === "pnj" && 
             actor.system.categorie === "Client";
    });
  }

  /**
   * Récupère les clés des caractéristiques
   */
  static #getCharacteristicKeys() {
    return Object.entries(DONJON_ET_CIE.characteristics).map(([key, metadata]) => ({
      key,
      label: metadata.label,
      short: metadata.short
    }));
  }

  /**
   * Prépare les données d'un PJ pour l'affichage
   */
  static async #preparePcData(pc, characteristicKeys) {
    const sys = pc.system || {};
    const items = pc.items?.contents || [];
    
    const pvValue = sys.sante?.pv?.value ?? 0;
    const pvMax = sys.sante?.pv?.max ?? 0;
    const dv = sys.sante?.dv ?? "1d6";
    const meleeAttacks = sys.combat?.attaquesCorpsACorps ?? 1;
    const rangedAttacks = sys.combat?.attaquesDistance ?? 1;
    
    const magicResources = DonjonEtCieUtility.getMagicResourceContext(pc);
    
    const weapons = [];
    const armors = [];
    const spells = [];
    const capacities = [];
    
    for (const item of items) {
      const itemSys = item.system || {};
      
      if (item.type === "arme") {
        const categoryLabel = itemSys.categorie === "distance" ? "Distance" : "Corps à corps";
        const handsLabel = (itemSys.mains ?? 1) > 1 ? "2 mains" : "1 main";
        
        weapons.push({
          name: item.name,
          categoryLabel,
          handsLabel,
          damage: itemSys.degatsEstUsageDe 
            ? `${itemSys.degats}(Δ)` 
            : (itemSys.degats || "—"),
          range: itemSys.portee || "Contact",
          ammunition: itemSys.munitionsDelta != null 
            ? (itemSys.munitionsDelta === 0 ? "Épuisées" : `Δ${itemSys.munitionsDelta}`)
            : ""
        });
      }
      
      if (item.type === "armure") {
        armors.push({
          name: item.name,
          protectionDie: `Δ${itemSys.delta || 0}`,
          encumbrance: itemSys.encombrement || "—",
          remainingProtection: itemSys.resultatProtection || "—"
        });
      }
      
      if (item.type === "sortilege") {
        spells.push({
          name: item.name,
          usageLabel: itemSys.delta > 0 ? DonjonEtCieUtility.formatUsageDie(itemSys.delta) : null
        });
      }
      
      if (item.type === "capacite") {
        capacities.push({
          name: item.name,
          usageLabel: itemSys.delta > 0 ? DonjonEtCieUtility.formatUsageDie(itemSys.delta) : null
        });
      }
    }
    
    // Spread des valeurs de caractéristiques directement sur l'objet pc
    const characteristics = {};
    characteristicKeys.forEach(({ key }) => {
      characteristics[key] = sys.caracteristiques?.[key]?.value ?? 0;
    });
    
    return {
      actorId: pc.id,
      name: pc.name,
      concept: pc.system.concept || "",
      pvValue,
      pvMax,
      dv,
      meleeAttacks,
      rangedAttacks,
      weapons,
      armors,
      spells,
      capacities,
      magicRank: magicResources.rank,
      focusDisplay: magicResources.focusDisplay,
      chaosDisplay: magicResources.chaosLabel,
      ...characteristics
    };
  }

  /**
   * Prépare les données d'un client (PNJ) depuis son TokenDocument
   */
  static #prepareClientData(token) {
    const client = token.actor;
    const sys = client.system || {};
    const items = client.items?.contents || [];

    // Attaques système du modèle PNJ
    const attaques = (sys.attaques || []).filter(a => a.nom || a.degats);

    // Items du PNJ
    const weapons = [];
    const spells = [];
    const capacities = [];

    for (const item of items) {
      const itemSys = item.system || {};
      if (item.type === "arme") {
        weapons.push({
          name: item.name,
          damage: itemSys.degatsEstUsageDe
            ? `${itemSys.degats}(Δ)` 
            : (itemSys.degats || "—"),
          categoryLabel: itemSys.categorie === "distance" ? "Distance" : "Corps à corps"
        });
      }
      if (item.type === "sortilege") {
        spells.push({
          name: item.name,
          usageLabel: itemSys.delta > 0 ? DonjonEtCieUtility.formatUsageDie(itemSys.delta) : null
        });
      }
      if (item.type === "capacite") {
        capacities.push({
          name: item.name,
          usageLabel: itemSys.delta > 0 ? DonjonEtCieUtility.formatUsageDie(itemSys.delta) : null
        });
      }
    }

    return {
      id: client.id,
      tokenUuid: token.uuid,
      name: client.name,
      species: sys.espece || "",
      category: sys.categorie || "",
      role: sys.role || "",
      summary: sys.resume || "",
      pvValue: sys.sante?.pv?.value ?? 0,
      pvMax: sys.sante?.pv?.max ?? 0,
      dv: sys.sante?.dv || "1d8",
      armureDelta: sys.defense?.armure?.delta ?? 0,
      armureProtection: sys.defense?.armure?.resultatProtection ?? 0,
      courageDelta: sys.defense?.courage?.delta ?? 0,
      attaques,
      weapons,
      spells,
      capacities,
      pouvoirsSpeciaux: sys.pouvoirsSpeciaux || "",
      hasMagie: spells.length > 0 || capacities.length > 0 || !!(sys.pouvoirsSpeciaux || "").trim()
    };
  }

  /**
   * Configuration des onglets à 2 niveaux
   * Niveau 1 : Employés / Clients (root tabs)
   * Niveau 2 : un onglet par PC ou par client (sub-tabs)
   */
  static #setupTabs(dialog) {
    const root = dialog.element;

    // ---- Onglets racine ----
    const rootTabs = root.querySelectorAll('.dnc-root-tab');
    const rootPanels = root.querySelectorAll('.dnc-root-panel');

    const activateRoot = (tabName) => {
      rootTabs.forEach(btn => btn.classList.toggle('active', btn.dataset.rootTab === tabName));
      rootPanels.forEach(panel => panel.classList.toggle('active', panel.dataset.rootPanel === tabName));
    };

    rootTabs.forEach(btn => {
      btn.addEventListener('click', (e) => {
        e.preventDefault();
        e.stopPropagation();
        activateRoot(btn.dataset.rootTab);
      });
    });

    // Activer premier onglet racine par défaut
    if (rootTabs.length > 0) activateRoot(rootTabs[0].dataset.rootTab);

    // ---- Sous-onglets PC ----
    const pcTabs = root.querySelectorAll('.dnc-pc-tab[data-pc-tab]');
    const pcPanels = root.querySelectorAll('.dnc-pc-panel[data-pc-panel]');

    const activatePc = (actorId) => {
      pcTabs.forEach(btn => btn.classList.toggle('active', btn.dataset.pcTab === actorId));
      pcPanels.forEach(panel => panel.classList.toggle('active', panel.dataset.pcPanel === actorId));
    };

    pcTabs.forEach(btn => {
      btn.addEventListener('click', (e) => {
        e.preventDefault();
        e.stopPropagation();
        activatePc(btn.dataset.pcTab);
      });
    });

    if (pcTabs.length > 0) activatePc(pcTabs[0].dataset.pcTab);

    // ---- Sous-onglets Clients ----
    const clientTabs = root.querySelectorAll('.dnc-pc-tab[data-client-tab]');
    const clientPanels = root.querySelectorAll('.dnc-client-panel[data-client-panel]');

    const activateClient = (clientId) => {
      clientTabs.forEach(btn => btn.classList.toggle('active', btn.dataset.clientTab === clientId));
      clientPanels.forEach(panel => panel.classList.toggle('active', panel.dataset.clientPanel === clientId));
    };

    clientTabs.forEach(btn => {
      btn.addEventListener('click', (e) => {
        e.preventDefault();
        e.stopPropagation();
        activateClient(btn.dataset.clientTab);
      });
    });

    if (clientTabs.length > 0) activateClient(clientTabs[0].dataset.clientTab);

    // ---- Ouverture des fiches ----
    root.addEventListener('click', (e) => {
      const btn = e.target.closest('.dnc-open-sheet-btn');
      if (!btn) return;
      e.preventDefault();
      e.stopPropagation();

      const type = btn.dataset.openSheet;
      if (type === "pc") {
        const actor = game.actors.get(btn.dataset.actorId);
        actor?.sheet.render(true);
      } else if (type === "client") {
        const tokenDoc = fromUuidSync(btn.dataset.tokenUuid);
        const actor = tokenDoc?.actor ?? game.actors.get(btn.dataset.actorId);
        actor?.sheet.render(true);
      }
    });

    // ---- Jets de dés depuis la vue clients (même dialogs que la fiche PNJ) ----
    root.addEventListener('click', async (e) => {
      const btn = e.target.closest('.dnc-roll-btn, .dnc-carac-rollable');
      if (!btn) return;
      e.preventDefault();
      e.stopPropagation();

      // Résolution de l'actor : token UUID pour gérer les tokens non-liés
      const tokenUuid = btn.dataset.tokenUuid;
      const actorId = btn.dataset.actorId;
      let actor = null;
      if (tokenUuid) {
        const tokenDoc = fromUuidSync(tokenUuid);
        actor = tokenDoc?.actor ?? null;
      }
      if (!actor && actorId) {
        actor = game.actors.get(actorId);
      }
      if (!actor) return;

      const action = btn.dataset.pnjAction;
      switch (action) {
        case "rollArmure":   return actor.rollPnjArmor();
        case "rollCourage":  return actor.rollPnjCourage();
        case "rollAttaque":  return actor.rollPnjAttackDamage(btn.dataset.attackIndex ?? 0);
      }
    });
  }
}

