/**
 * Module Initialization Tests - Tests E2E
 * 
 * Vérifie que le module Scrying Pool s'initialise correctement
 * dans FoundryVTT et que toutes les fonctionnalités de base sont disponibles.
 */

import { test, expect } from '@playwright/test';
import {
  waitForFoundryReady,
  waitForVVMModule,
  clickFoundryButton,
} from '../utils/foundry-helpers';

const MODULE_ID = 'scrying-pool';
const MODULE_NAME = 'Scrying Pool';

test.describe('Module Initialization', () => {
  test.setTimeout(60000);

  test.beforeEach(async ({ page }) => {
    await page.goto('https://localhost:31000', {
      waitUntil: 'domcontentloaded',
      timeout: 30000,
    });
    
    await waitForFoundryReady(page);
  });

  // ============================================================================
  // Initialisation de base
  // ============================================================================

  test('Module is registered in FoundryVTT', async ({ page }) => {
    const module = await page.evaluate((moduleId) => {
      return game.modules?.get(moduleId);
    }, MODULE_ID);
    
    expect(module).toBeTruthy();
    expect(module?.id).toBe(MODULE_ID);
  });

  test('Module has correct name', async ({ page }) => {
    const module = await page.evaluate((moduleId) => {
      return game.modules?.get(moduleId);
    }, MODULE_ID);
    
    expect(module?.data?.title).toContain(MODULE_NAME);
  });

  test('Module is active', async ({ page }) => {
    await waitForVVMModule(page);
    
    const isActive = await page.evaluate((moduleId) => {
      const module = game.modules?.get(moduleId);
      return module?.active;
    }, MODULE_ID);
    
    expect(isActive).toBe(true);
  });

  test('Module loads without errors', async ({ page }) => {
    // Vérifier qu'il n'y a pas d'erreurs dans la console
    const errors = [];
    
    page.on('console', msg => {
      if (msg.type() === 'error') {
        errors.push(msg.text());
      }
    });
    
    await waitForVVMModule(page);
    await page.waitForTimeout(2000);
    
    // Filtrer les erreurs connues (qui ne sont pas liées à notre module)
    const vvmErrors = errors.filter(err => err.includes('ScryingPool') || err.includes(MODULE_ID));
    
    expect(vvmErrors).toHaveLength(0);
  });

  // ============================================================================
  // Vérification des composants
  // ============================================================================

  test('ScryingPoolStrip is available for GM', async ({ page }) => {
    await waitForVVMModule(page);
    
    const isGM = await page.evaluate(() => game.user?.isGM || false);
    
    if (isGM) {
      // L'application ScryingPoolStrip devrait être enregistrée
      const app = await page.evaluate((moduleId) => {
        const module = game.modules?.get(moduleId);
        if (module && module.api?.roleRenderer) {
          return module.api.roleRenderer._strip;
        }
        return null;
      }, MODULE_ID);
      
      // Devrait exister après l'initialisation
      expect(app).toBeTruthy();
    }
  });

  test('VisibilityBadges are injected into AV tiles', async ({ page }) => {
    await waitForVVMModule(page);
    
    // Attendre que les badges soient injectés
    await page.waitForSelector('.sp-visibility-badge', {
      state: 'visible',
      timeout: 10000,
    });
    
    const badges = page.locator('.sp-visibility-badge');
    expect(await badges.count()).toBeGreaterThan(0);
  });

  test('ScryingPoolController is initialized', async ({ page }) => {
    await waitForVVMModule(page);
    
    const controller = await page.evaluate((moduleId) => {
      const module = game.modules?.get(moduleId);
      return module?.api?.controller;
    }, MODULE_ID);
    
    expect(controller).toBeTruthy();
  });

  test('StateStore is initialized with correct data', async ({ page }) => {
    await waitForVVMModule(page);
    
    const stateStore = await page.evaluate((moduleId) => {
      const module = game.modules?.get(moduleId);
      return module?.api?.stateStore;
    }, MODULE_ID);
    
    expect(stateStore).toBeTruthy();
    
    // Vérifier que la matrice de visibilité existe
    const matrix = await page.evaluate((moduleId) => {
      const module = game.modules?.get(moduleId);
      if (module?.api?.stateStore) {
        return module.api.stateStore.getMatrix();
      }
      return null;
    }, MODULE_ID);
    
    expect(matrix).toBeTruthy();
    expect(matrix).toHaveProperty('_version');
    expect(matrix).toHaveProperty('matrix');
  });

  test('SocketHandler is registered', async ({ page }) => {
    await waitForVVMModule(page);
    
    const socketHandler = await page.evaluate((moduleId) => {
      const module = game.modules?.get(moduleId);
      return module?.api?.socketHandler;
    }, MODULE_ID);
    
    expect(socketHandler).toBeTruthy();
  });

  test('VisibilityManager is initialized', async ({ page }) => {
    await waitForVVMModule(page);
    
    const visibilityManager = await page.evaluate((moduleId) => {
      const module = game.modules?.get(moduleId);
      return module?.api?.visibilityManager;
    }, MODULE_ID);
    
    expect(visibilityManager).toBeTruthy();
  });

  // ============================================================================
  // Vérification des paramètres
  // ============================================================================

  test('World settings are registered', async ({ page }) => {
    await waitForVVMModule(page);
    
    const settings = await page.evaluate((moduleId) => {
      const module = game.modules?.get(moduleId);
      if (module) {
        return Array.from(game.settings.settings.entries())
          .filter(([key]) => key.startsWith(`${moduleId}.`))
          .map(([key, value]) => key);
      }
      return [];
    }, MODULE_ID);
    
    expect(settings.length).toBeGreaterThan(0);
    expect(settings).toContain(`${MODULE_ID}.webrtcMode`);
  });

  test('Client settings are registered', async ({ page }) => {
    await waitForVVMModule(page);
    
    const clientSettings = await page.evaluate((moduleId, userId) => {
      const module = game.modules?.get(moduleId);
      if (module && game.users?.get(userId)) {
        const user = game.users.get(userId);
        return Array.from(user.getSettings().entries())
          .filter(([key]) => key.includes(moduleId))
          .map(([key]) => key);
      }
      return [];
    }, MODULE_ID, 'gamemaster');
    
    expect(clientSettings.length).toBeGreaterThan(0);
  });

  // ============================================================================
  // Vérification des menus
  // ============================================================================

  test('GM Player Privacy Selector menu is registered', async ({ page }) => {
    await waitForVVMModule(page);
    
    const isGM = await page.evaluate(() => game.user?.isGM || false);
    
    if (isGM) {
      // Le menu devrait être disponible dans les paramètres
      const menuItem = page.locator('button:has-text("Player Privacy")');
      await expect(menuItem).toBeVisible({ timeout: 10000 });
    }
  });

  // ============================================================================
  // Vérification des hooks
  // ============================================================================

  test('Hooks are registered correctly', async ({ page }) => {
    await waitForVVMModule(page);
    
    // Vérifier que les hooks sont enregistrés
    const hooks = await page.evaluate((moduleId) => {
      const module = game.modules?.get(moduleId);
      if (module && game.hooks) {
        const hookEvents = [];
        for (const [event, handlers] of game.hooks.events.entries()) {
          if (event.startsWith('scrying-pool.')) {
            hookEvents.push(event);
          }
        }
        return hookEvents;
      }
      return [];
    }, MODULE_ID);
    
    expect(hooks.length).toBeGreaterThan(0);
    expect(hooks).toContain('scrying-pool:stateChanged');
  });

  // ============================================================================
  // Vérification des styles
  // ============================================================================

  test('Module CSS is loaded', async ({ page }) => {
    await waitForVVMModule(page);
    
    // Vérifier qu'une classe CSS du module existe
    const element = page.locator('.scrying-pool');
    
    // Devrait exister même s'il n'est pas visible
    expect(await element.count()).toBeGreaterThan(0);
  });

  test('Design tokens are defined', async ({ page }) => {
    await waitForVVMModule(page);
    
    const tokens = await page.evaluate(() => {
      const style = getComputedStyle(document.documentElement);
      const tokenNames = [
        '--sp-surface',
        '--sp-border',
        '--sp-text-primary',
        '--sp-text-secondary',
        '--sp-accent',
      ];
      
      return tokenNames.filter(name => style.getPropertyValue(name).trim() !== '');
    });
    
    expect(tokens.length).toBeGreaterThan(0);
  });

  // ============================================================================
  // Vérification des templates
  // ============================================================================

  test('Handlebars templates are precompiled', async ({ page }) => {
    await waitForVVMModule(page);
    
    // Vérifier que les templates sont disponibles
    const templates = await page.evaluate((moduleId) => {
      const module = game.modules?.get(moduleId);
      if (module && game.templates) {
        const templatePrefix = `modules/${moduleId}/templates/`;
        return Array.from(game.templates.cache.keys())
          .filter(key => key.startsWith(templatePrefix))
          .map(key => key.replace(templatePrefix, ''));
      }
      return [];
    }, MODULE_ID);
    
    expect(templates.length).toBeGreaterThan(0);
  });

  // ============================================================================
  // Vérification des localisations
  // ============================================================================

  test('Localization strings are available', async ({ page }) => {
    await waitForVVMModule(page);
    
    const i18nKeys = await page.evaluate((moduleId) => {
      const module = game.modules?.get(moduleId);
      if (module && game.i18n) {
        const langData = game.i18n.getLanguages();
        const moduleKeys = [];
        
        for (const [lang, translations] of Object.entries(langData)) {
          for (const [key] of Object.entries(translations)) {
            if (key.startsWith(`${moduleId}.`)) {
              moduleKeys.push(key);
            }
          }
        }
        
        return moduleKeys;
      }
      return [];
    }, MODULE_ID);
    
    expect(i18nKeys.length).toBeGreaterThan(0);
  });
});
