import { CommerceDialog } from './CommerceDialog.js';
import { NpcDialog } from './NpcDialog.js';
import { SectorMapApp } from './SectorMapApp.js';

const MODULE_ID = 'mgt2-compendium-amiral-denisov';
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;

const IMAGE_EXTENSIONS = new Set(['png', 'webp', 'jpg', 'jpeg', 'gif', 'svg', 'avif', 'bmp', 'tiff', 'tif']);

class BatchNpcDialog extends HandlebarsApplicationMixin(ApplicationV2) {
  static DEFAULT_OPTIONS = {
    id: 'mgt2-batch-npc',
    classes: ['mgt2-npc-dialog'],
    position: { width: 540, height: 'auto' },
    window: { title: 'Création de PNJs par lots', resizable: true },
    form: { submitOnClose: false, closeOnSubmit: false },
  };

  static PARTS = {
    main: {
      template: `modules/${MODULE_ID}/templates/batch-npc-dialog.hbs`,
      root: true,
    },
  };

  constructor(options = {}) {
    super(options);
    this._formData = {
      batch: {
        directory: '',
        folderName: 'PNJs importés',
        openSheets: false,
      },
    };
  }

  async _prepareContext() {
    return { ...this._formData };
  }

  async _onRender(context, options) {
    await super._onRender(context, options);
    const html = $('#' + this.id).find('.window-content');

    this._applyTheme(html);

    html.find('[data-action="browse-directory"]').on('click', async () => {
      // Foundry v14: FilePicker avec pickFolders pour sélectionner un répertoire
      try {
        const fp = new FilePicker({
          type: 'folder',
          current: this._formData.batch.directory || '',
          callback: (path) => {
            this._formData.batch.directory = path;
            html.find('[name="batch.directory"]').val(path);
          },
          pickFolders: true,
          field: null,
          button: null,
        });
        fp.render(true);
        return;
      } catch (_e) { /* fallback v13 */ }
      // Fallback v13: selection d'un fichier → extraction du dossier parent
      const fp = new FilePicker({
        type: 'image',
        current: this._formData.batch.directory || '',
        callback: (path) => {
          const dir = path.split('/').slice(0, -1).join('/');
          this._formData.batch.directory = dir;
          html.find('[name="batch.directory"]').val(dir);
        },
      });
      fp.render(true);
    });

    html.find('[data-action="batch-create"]').on('click', async () => {
      this._readForm(html);
      await this._executeBatch(html);
    });
  }

  _readForm(html) {
    this._formData.batch.directory = (html.find('[name="batch.directory"]').val()?.trim() || '').replace(/\/+$/, '');
    this._formData.batch.folderName = html.find('[name="batch.folderName"]').val()?.trim() || 'PNJs importés';
    this._formData.batch.openSheets = html.find('[name="batch.openSheets"]').is(':checked');
  }

  _applyTheme(html) {
    html.find('h3').css({ color: '#5f4300', 'border-bottom-color': '#b78f26', 'text-shadow': 'none' });
    html.find('legend').css({ color: '#7a5c00', 'text-shadow': 'none' });
  }

  async _executeBatch(html) {
    const { directory, folderName, openSheets } = this._formData.batch;

    if (!directory) {
      ui.notifications.warn('Veuillez spécifier un répertoire source.');
      return;
    }

    const $progress = html.find('#batch-progress');
    const $fill = html.find('#batch-progress-fill');
    const $text = html.find('#batch-progress-text');
    $progress.show();

    try {
      $text.text('Analyse du répertoire...');

      let files;
      try {
        const result = await FilePicker.browse('data', directory);
        files = result.files || [];
      } catch (e) {
        $progress.hide();
        ui.notifications.error(`Impossible de lire le répertoire « ${directory} » : ${e.message}`);
        return;
      }

      const imageFiles = files.filter(f => {
        const ext = f.split('.').pop()?.toLowerCase();
        return ext && IMAGE_EXTENSIONS.has(ext);
      });

      if (imageFiles.length === 0) {
        $progress.hide();
        ui.notifications.warn(`Aucune image trouvée dans « ${directory} ».`);
        return;
      }

      $text.text(`${imageFiles.length} image(s) trouvée(s). Vérification des doublons...`);

      const normalizePath = (p) => p.replace(/^[\\/]+/, '').replace(/[\\/]+/g, '/').toLowerCase();

      const existingImages = new Set();
      for (const actor of game.actors) {
        if (actor.img && actor.img !== 'icons/svg/mystery-man.svg') {
          existingImages.add(normalizePath(actor.img));
        }
      }

      const toCreate = imageFiles.filter(f => !existingImages.has(normalizePath(f)));

      if (toCreate.length === 0) {
        $progress.hide();
        ui.notifications.info('Tous les PNJs existent déjà (aucune nouvelle image à traiter).');
        return;
      }

      let folder = null;
      if (folderName) {
        folder = game.folders.find(f => f.name === folderName && f.type === 'Actor');
        if (!folder) {
          folder = await Folder.create({ name: folderName, type: 'Actor', parent: null });
        }
      }

      $text.text(`Création de ${toCreate.length} PNJ(s)...`);

      const chunkSize = 10;
      let created = 0;
      const allCreated = [];

      for (let i = 0; i < toCreate.length; i += chunkSize) {
        const chunk = toCreate.slice(i, i + chunkSize);
        const actorsData = chunk.map(path => {
          const name = path.split('/').pop().replace(/\.[^/.]+$/, '');
          return {
            name,
            type: 'npc',
            img: path,
            folder: folder?.id || null,
            token: {
              name,
              img: path,
              actorLink: true,
              disposition: 0,
              sight: { enabled: false },
            },
            system: {
              settings: { hideUntrained: true, lockCharacteristics: true },
              characteristics: {},
              hits: {},
              skills: {},
            },
            flags: {
              [MODULE_ID]: { batchImported: true, sourceImage: path },
            },
          };
        });

        const actors = await Actor.create(actorsData, { renderSheet: false });
        allCreated.push(...actors);
        created += actors.length;

        const pct = Math.min(100, Math.round((i + chunkSize) / toCreate.length * 100));
        $fill.css('width', pct + '%');
        $text.text(`${created}/${toCreate.length} PNJ(s) créé(s)...`);
      }

      ui.actors?.render(false);

      $fill.css('width', '100%');
      $text.text(`${created} PNJ(s) créé(s) avec succès dans le dossier « ${folderName} » !`);
      ui.notifications.info(`${created} PNJ(s) créé(s) à partir des images.`);

      if (openSheets && allCreated.length > 0) {
        const lastActor = allCreated[allCreated.length - 1];
        if (lastActor) lastActor.sheet?.render(true);
      }

    } catch (error) {
      console.error(`${MODULE_ID} | Batch NPC creation error:`, error);
      $text.text(`Erreur : ${error.message}`);
      ui.notifications.error(`Erreur lors de la création : ${error.message}`);
    }
  }
}

Hooks.on('renderActorDirectory', (app, html, data) => {
  if (!game.user?.isGM) return;
  const $html = html instanceof jQuery ? html : $(html);
  if ($html.find('.mgt2-batch-npc-btn').length) return;

  const btn = $(`<button class="mgt2-batch-npc-btn" style="margin:4px 8px;flex:0;background:#2c2c3e;color:#d9b24c;border:1px solid #c9a227;">
    <i class="fas fa-users"></i> Importer PNJs par lots
  </button>`);

  const shortcuts = [
    { icon: 'fa-balance-scale', label: 'Commerce', abbr: 'Commerce', action: 'commerce', cls: 'mgt2-shortcut-commerce', title: 'Ouvrir le commerce' },
    { icon: 'fa-user', label: 'PNJ rapide', abbr: 'PNJ', action: 'npc', cls: 'mgt2-shortcut-pnj', title: 'Générer un PNJ rapide' },
    { icon: 'fa-random', label: 'Rencontre', abbr: 'Rencontre', action: 'encounter', cls: 'mgt2-shortcut-rencontre', title: 'Générer une rencontre' },
    { icon: 'fa-briefcase', label: 'Mission', abbr: 'Mission', action: 'mission', cls: 'mgt2-shortcut-mission', title: 'Générer une mission' },
    { icon: 'fa-image', label: 'Fermer portraits', abbr: 'Fermer img', action: 'closePortraits', cls: 'mgt2-shortcut-closeimg', title: 'Fermer les portraits affichés aux joueurs' },
  ];

  const grid = $(`<div style="display:grid;grid-template-columns:1fr 1fr;gap:4px;margin:4px 8px;"></div>`);
  shortcuts.forEach(s => {
    const b = $(`<button class="${s.cls}" title="${s.title}" style="background:#2c2c3e;color:#d9b24c;border:1px solid #c9a227;padding:4px 6px;font-size:0.78em;cursor:pointer;border-radius:3px;text-align:center;">
      <i class="fas ${s.icon}"></i> ${s.abbr}
    </button>`).on('click', () => {
      if (s.action === 'commerce') new CommerceDialog().render({ force: true });
      else if (s.action === 'closePortraits') {
        game.socket.emit(`module.${MODULE_ID}`, { _type: 'closeImagePopout' });
        ui.notifications.info('Fermeture des portraits envoyée aux joueurs');
      }
      else new NpcDialog({ initialTab: s.action }).render({ force: true });
    });
    grid.append(b);
  });

  const footer = $html.find('.directory-footer');
  if (footer.length) {
    footer.append(btn);
    footer.append(grid);
  } else {
    $html.find('.directory-header').after(btn);
    $html.find('.directory-header').after(grid);
  }

  btn.on('click', () => {
    new BatchNpcDialog().render({ force: true });
  });
});

Hooks.on('renderSceneDirectory', (app, html, data) => {
  if (!game.user?.isGM) return;
  const $html = html instanceof jQuery ? html : $(html);
  if ($html.find('.mgt2-sector-btn').length) return;

  const sectorBtn = $(`<button class="mgt2-sector-btn" style="margin:4px 8px;flex:0;background:#2c2c3e;color:#d9b24c;border:1px solid #c9a227;cursor:pointer;">
    <i class="fas fa-map"></i> Traveller Map
  </button>`).on('click', () => {
    new SectorMapApp().render({ force: true });
  });

  const canvasBtn = $(`<button class="mgt2-canvas-sync-btn" style="margin:4px 8px;flex:0;background:#2c2c3e;color:#d9b24c;border:1px solid #c9a227;cursor:pointer;">
    <i class="fas fa-eye"></i> Sync vue MJ
  </button>`).on('click', () => {
    const pivot = canvas.stage?.pivot;
    const scale = canvas.stage?.scale?.x;
    if (!pivot || !scale) { ui.notifications.warn('Canvas pas encore prêt'); return; }
    const players = game.users.filter(u => !u.isGM && u.active).map(u => u.id);
    if (!players.length) { ui.notifications.warn('Aucun joueur connecté'); return; }
    game.socket.emit(`module.${MODULE_ID}`, {
      _type: 'canvasSync',
      x: pivot.x,
      y: pivot.y,
      scale,
    });
    ui.notifications.info(`Vue synchronisée chez ${players.length} joueur(s)`);
  });

  const grid = $(`<div style="display:grid;grid-template-columns:1fr 1fr;gap:4px;margin:4px 8px;"></div>`);
  grid.append(sectorBtn, canvasBtn);

  const footer = $html.find('.directory-footer');
  if (footer.length) footer.append(grid);
  else $html.find('.directory-header').after(grid);
});
