/**
 * Helpers pour les tests E2E avec FoundryVTT
 * 
 * Fournit des fonctions utilitaires pour :
 * - Attendre que Foundry soit prêt
 * - Attendre que le module soit chargé
 * - Interagir avec l'UI FoundryVTT
 * - Gérer les sélecteurs spécifiques au module
 */

import { expect } from '@playwright/test';

/**
 * Attend que FoundryVTT soit complètement chargé
 * @param {import('@playwright/test').Page} page - La page Playwright
 * @param {number} timeout - Timeout en ms (défaut: 30000)
 */
export async function waitForFoundryReady(page, timeout = 30000) {
  await page.waitForFunction(() => {
    return typeof game !== 'undefined' && game.ready;
  }, { timeout });
}

/**
 * Attend que le module Scrying Pool soit actif
 * @param {import('@playwright/test').Page} page - La page Playwright
 * @param {number} timeout - Timeout en ms (défaut: 15000)
 */
export async function waitForVVMModule(page, timeout = 15000) {
  await page.waitForFunction(() => {
    const module = game.modules?.get?.('scrying-pool');
    return module?.active === true;
  }, { timeout });
}

/**
 * Attend qu'un élément du module soit présent
 * @param {import('@playwright/test').Page} page - La page Playwright
 * @param {string} selector - Sélecteur CSS
 * @param {number} timeout - Timeout en ms (défaut: 10000)
 */
export async function waitForVVMElement(page, selector, timeout = 10000) {
  await page.waitForSelector(selector, { 
    state: 'visible',
    timeout 
  });
}

/**
 * Clique sur un bouton dans l'UI Foundry avec retry
 * @param {import('@playwright/test').Page} page - La page Playwright
 * @param {string|import('@playwright/test').Locator} button - Sélecteur ou Locator
 * @param {number} retries - Nombre de tentatives (défaut: 3)
 */
export async function clickFoundryButton(page, button, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      const locator = typeof button === 'string' ? page.locator(button) : button;
      await locator.click({ timeout: 5000 });
      return;
    } catch (error) {
      if (i === retries - 1) throw error;
      await page.waitForTimeout(1000);
    }
  }
}

/**
 * Ouvre le sidebar de configuration Foundry
 * @param {import('@playwright/test').Page} page - La page Playwright
 */
export async function openFoundrySidebar(page) {
  await clickFoundryButton(page, 'button[aria-label="Configure Settings"]');
  await page.waitForSelector('.app-v2.settings', { state: 'visible', timeout: 10000 });
}

/**
 * Ouvre le Director's Board (Epic 2)
 * @param {import('@playwright/test').Page} page - La page Playwright
 */
export async function openDirectorsBoard(page) {
  // Le Director's Board a un bouton dédié dans la sidebar
  await page.waitForSelector('button[aria-label*="Director\'s Board"]', { timeout: 10000 });
  await clickFoundryButton(page, 'button[aria-label*="Director\'s Board"]');
  
  // Attendre que le board soit ouvert
  await page.waitForSelector('.scrying-pool-directors-board', { 
    state: 'visible',
    timeout: 10000 
  });
}

/**
 * Ouvre le Player Privacy Panel pour un utilisateur
 * @param {import('@playwright/test').Page} page - La page Playwright
 * @param {string} userId - L'ID de l'utilisateur
 */
export async function openPlayerPrivacyPanel(page, userId) {
  // Le panel s'ouvre via les paramètres du module
  await openFoundrySidebar(page);
  
  // Naviguer vers les paramètres du module
  await clickFoundryButton(page, 'button:has-text("Scrying Pool")');
  await page.waitForTimeout(1000);
  
  // Cliquer sur le bouton Player Privacy
  await clickFoundryButton(page, 'button:has-text("Player Privacy")');
  
  // Attendre le panel
  await page.waitForSelector('.sp-player-privacy-panel', { 
    state: 'visible',
    timeout: 10000 
  });
}

/**
 * Sélectionne un utilisateur dans une liste Foundry
 * @param {import('@playwright/test').Page} page - La page Playwright
 * @param {string} username - Le nom de l'utilisateur
 */
export async function selectUserInList(page, username) {
  const userItem = page.locator(`.sp-user-item:has-text("${username}")`);
  await userItem.click({ timeout: 5000 });
  await page.waitForTimeout(500);
}

/**
 * Attend qu'une notification Foundry apparaisse
 * @param {import('@playwright/test').Page} page - La page Playwright
 * @param {string} text - Texte de la notification
 * @param {number} timeout - Timeout en ms
 */
export async function waitForNotification(page, text, timeout = 10000) {
  await page.waitForSelector(
    `.notification:has-text("${text}")`,
    { state: 'visible', timeout }
  );
}

/**
 * Vérifie qu'un AV Tile a un badge de visibilité spécifique
 * @param {import('@playwright/test').Page} page - La page Playwright
 * @param {string} userId - L'ID de l'utilisateur
 * @param {string} state - L'état attendu (active, hidden, etc.)
 */
export async function verifyAVTileState(page, userId, state) {
  const tile = page.locator(`[data-user-id="${userId}"] .sp-visibility-badge`);
  await expect(tile).toBeVisible({ timeout: 5000 });
  
  // Vérifier le texte ou la classe CSS
  const expectedText = {
    active: 'Live',
    hidden: 'Hidden from table',
    'self-muted': 'Camera paused',
    offline: 'Not connected',
    'cam-lost': 'Camera unavailable',
    reconnecting: 'Rejoining view',
    'never-connected': 'Not yet connected',
    ghost: 'Leaving',
  }[state];
  
  if (expectedText) {
    await expect(tile).toContainText(expectedText);
  }
}

/**
 * Charge un preset de scène
 * @param {import('@playwright/test').Page} page - La page Playwright
 * @param {string} presetName - Le nom du preset
 */
export async function loadScenePreset(page, presetName) {
  await openDirectorsBoard(page);
  
  // Cliquer sur le bouton Load Preset
  await clickFoundryButton(page, 'button:has-text("Load Preset")');
  
  // Sélectionner le preset dans la liste
  await page.waitForSelector('.sp-preset-list', { state: 'visible', timeout: 5000 });
  await clickFoundryButton(page, `.sp-preset-item:has-text("${presetName}")`);
  
  // Attendre la confirmation
  await waitForNotification(page, `Applied preset: ${presetName}`, 5000);
}

/**
 * Sauvegarde le preset courant
 * @param {import('@playwright/test').Page} page - La page Playwright
 * @param {string} presetName - Le nom du preset
 */
export async function saveScenePreset(page, presetName) {
  await openDirectorsBoard(page);
  
  // Cliquer sur Save Preset
  await clickFoundryButton(page, 'button:has-text("Save Preset")');
  
  // Remplir le nom du preset
  await page.waitForSelector('.sp-save-preset-dialog', { state: 'visible', timeout: 5000 });
  await page.locator('.sp-save-preset-dialog input[name="presetName"]').fill(presetName);
  
  // Confirmer
  await clickFoundryButton(page, '.sp-save-preset-dialog button:has-text("Save")');
  
  // Attendre la confirmation
  await waitForNotification(page, `Saved preset: ${presetName}`, 5000);
}

/**
 * Hide un participant via le context menu
 * @param {import('@playwright/test').Page} page - La page Playwright
 * @param {string} username - Le nom du participant
 */
export async function hideParticipant(page, username) {
  // Trouver la tuile AV du participant
  const tile = page.locator(`.av-tile:has-text("${username}")`);
  
  // Clic droit pour ouvrir le context menu
  await tile.click({ button: 'right', timeout: 5000 });
  
  // Sélectionner "Hide from table"
  await page.waitForSelector('.context-menu', { state: 'visible', timeout: 5000 });
  await clickFoundryButton(page, '.context-menu li:has-text("Hide from table")');
  
  // Attendre que le badge soit mis à jour
  await page.waitForTimeout(1000);
}

/**
 * Show un participant via le context menu
 * @param {import('@playwright/test').Page} page - La page Playwright
 * @param {string} username - Le nom du participant
 */
export async function showParticipant(page, username) {
  const tile = page.locator(`.av-tile:has-text("${username}")`);
  await tile.click({ button: 'right', timeout: 5000 });
  
  await page.waitForSelector('.context-menu', { state: 'visible', timeout: 5000 });
  await clickFoundryButton(page, '.context-menu li:has-text("Show to table")');
  
  await page.waitForTimeout(1000);
}

/**
 * Utilise le Director's Board pour toggler un participant
 * @param {import('@playwright/test').Page} page - La page Playwright
 * @param {string} username - Le nom du participant
 */
export async function toggleParticipantInBoard(page, username) {
  await openDirectorsBoard(page);
  
  // Trouver la carte du participant
  const card = page.locator(`.sp-participant-card:has-text("${username}")`);
  await card.click({ timeout: 5000 });
  
  // Le toggle devrait se faire automatiquement au clic
  await page.waitForTimeout(500);
}
