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

/**
 * Tests complets pour les Settings UX (Story 11-2)
 * 
 * Ce fichier teste toutes les fonctionnalités implémentées:
 * - General Settings: Notifications (Email), Privacy (Analytics)
 * - Profile Settings: Language, Font Size, Show Recent Notes
 * - Appearance Settings: Theme Persistence (Light/Dark/Auto)
 * - SettingsSearch: Functional search with filtering
 * 
 * Prérequis:
 * - Être connecté avec un compte utilisateur
 * - Avoir accès aux pages de settings
 * - Base de données avec les nouveaux champs (emailNotifications, anonymousAnalytics)
 */

test.describe('Settings UX - Story 11-2', () => {
  // Variables pour stocker les credentials
  let email: string
  let password: string

  test.beforeAll(async ({ browser }) => {
    // Les credentials seront fournis par l'utilisateur
    console.log('Credentials nécessaires pour exécuter les tests')
    console.log('Veuillez fournir email et password')
  })

  test.beforeEach(async ({ page }) => {
    // Se connecter avant chaque test
    await page.goto('http://localhost:3000/login')
    await page.fill('input[name="email"]', email)
    await page.fill('input[name="password"]', password)
    await page.click('button[type="submit"]')
    
    // Attendre la connexion et vérifier qu'on est sur la page d'accueil
    await page.waitForURL('**/main**')
    await expect(page).toHaveURL(/\/main/)
  })

  /**
   * Tests pour General Settings
   */
  test.describe('General Settings', () => {
    test('devrait afficher la page General Settings', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/general')
      
      // Vérifier le titre de la page
      const title = await page.textContent('h1')
      expect(title).toContain('General')
      
      // Vérifier que les sections sont présentes
      await expect(page.locator('#language')).toBeVisible()
      await expect(page.locator('#notifications')).toBeVisible()
      await expect(page.locator('#privacy')).toBeVisible()
    })

    test('devrait avoir le toggle Email Notifications', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/general')
      
      // Scroll vers la section notifications
      await page.locator('#notifications').scrollIntoViewIfNeeded()
      
      // Vérifier que le toggle est présent
      const emailToggle = page.getByRole('switch', { name: /email notifications/i })
      await expect(emailToggle).toBeVisible()
    })

    test('devrait pouvoir activer/désactiver Email Notifications', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/general')
      
      // Scroll vers la section notifications
      await page.locator('#notifications').scrollIntoViewIfNeeded()
      
      // Récupérer l'état initial du toggle
      const emailToggle = page.getByRole('switch', { name: /email notifications/i })
      const initialState = await emailToggle.getAttribute('aria-checked')
      const initialEnabled = initialState === 'true'
      
      // Cliquer sur le toggle
      await emailToggle.click()
      
      // Attendre un peu pour l'opération asynchrone
      await page.waitForTimeout(500)
      
      // Vérifier que l'état a changé
      const newState = await emailToggle.getAttribute('aria-checked')
      const newEnabled = newState === 'true'
      expect(newEnabled).toBe(!initialEnabled)
      
      // Vérifier qu'un toast de succès apparaît
      await expect(page.getByText(/success/i)).toBeVisible({ timeout: 3000 })
    })

    test('devrait avoir le toggle Anonymous Analytics', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/general')
      
      // Scroll vers la section privacy
      await page.locator('#privacy').scrollIntoViewIfNeeded()
      
      // Vérifier que le toggle est présent
      const analyticsToggle = page.getByRole('switch', { name: /anonymous analytics/i })
      await expect(analyticsToggle).toBeVisible()
    })

    test('devrait pouvoir activer/désactiver Anonymous Analytics', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/general')
      
      // Scroll vers la section privacy
      await page.locator('#privacy').scrollIntoViewIfNeeded()
      
      // Récupérer l'état initial du toggle
      const analyticsToggle = page.getByRole('switch', { name: /anonymous analytics/i })
      const initialState = await analyticsToggle.getAttribute('aria-checked')
      const initialEnabled = initialState === 'true'
      
      // Cliquer sur le toggle
      await analyticsToggle.click()
      
      // Attendre un peu pour l'opération asynchrone
      await page.waitForTimeout(500)
      
      // Vérifier que l'état a changé
      const newState = await analyticsToggle.getAttribute('aria-checked')
      const newEnabled = newState === 'true'
      expect(newEnabled).toBe(!initialEnabled)
      
      // Vérifier qu'un toast de succès apparaît
      await expect(page.getByText(/success/i)).toBeVisible({ timeout: 3000 })
    })

    test('devrait avoir le composant SettingsSearch', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/general')
      
      // Vérifier que la barre de recherche est présente
      const searchInput = page.getByPlaceholder(/search/i)
      await expect(searchInput).toBeVisible()
      
      // Vérifier l'icône de recherche
      await expect(page.locator('svg').filter({ hasText: '' }).first()).toBeVisible()
    })

    test('devrait filtrer les sections avec SettingsSearch', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/general')
      
      // Cliquer sur la barre de recherche
      const searchInput = page.getByPlaceholder(/search/i)
      await searchInput.click()
      
      // Taper "notification"
      await searchInput.fill('notification')
      
      // Vérifier que la section notifications est visible
      await expect(page.locator('#notifications')).toBeVisible()
      
      // Vérifier que les autres sections ne sont plus visibles (ou sont filtrées)
      // Note: Cela dépend de l'implémentation exacte du filtrage
    })

    test('devrait effacer la recherche avec le bouton X', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/general')
      
      const searchInput = page.getByPlaceholder(/search/i)
      await searchInput.fill('test')
      
      // Vérifier que le bouton X apparaît
      const clearButton = page.getByRole('button', { name: /clear search/i })
      await expect(clearButton).toBeVisible()
      
      // Cliquer sur le bouton X
      await clearButton.click()
      
      // Vérifier que la recherche est vide
      await expect(searchInput).toHaveValue('')
    })

    test('devrait effacer la recherche avec la touche Escape', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/general')
      
      const searchInput = page.getByPlaceholder(/search/i)
      await searchInput.fill('test')
      
      // Appuyer sur Escape
      await page.keyboard.press('Escape')
      
      // Vérifier que la recherche est vide
      await expect(searchInput).toHaveValue('')
    })
  })

  /**
   * Tests pour Profile Settings
   */
  test.describe('Profile Settings', () => {
    test('devrait afficher la page Profile Settings', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/profile')
      
      // Vérifier le titre de la page
      const title = await page.textContent('h1')
      expect(title).toContain('Profile')
      
      // Vérifier les sections
      await expect(page.getByText(/display name/i)).toBeVisible()
      await expect(page.getByText(/email/i)).toBeVisible()
      await expect(page.getByText(/language preferences/i)).toBeVisible()
      await expect(page.getByText(/display settings/i)).toBeVisible()
      await expect(page.getByText(/change password/i)).toBeVisible()
    })

    test('devrait avoir le sélecteur de langue', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/profile')
      
      // Scroll vers la section language
      await page.getByText(/language preferences/i).scrollIntoViewIfNeeded()
      
      // Vérifier que le sélecteur est présent
      const languageSelect = page.locator('#language')
      await expect(languageSelect).toBeVisible()
    })

    test('devrait pouvoir changer la langue', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/profile')
      
      // Scroll vers la section language
      await page.getByText(/language preferences/i).scrollIntoViewIfNeeded()
      
      // Cliquer sur le sélecteur
      const languageSelect = page.locator('#language')
      await languageSelect.click()
      
      // Sélectionner une langue (ex: français)
      await page.getByRole('option', { name: /français/i }).click()
      
      // Vérifier qu'un toast de succès apparaît
      await expect(page.getByText(/success/i)).toBeVisible({ timeout: 3000 })
    })

    test('devrait avoir le sélecteur de taille de police', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/profile')
      
      // Scroll vers la section display settings
      await page.getByText(/display settings/i).scrollIntoViewIfNeeded()
      
      // Vérifier que le sélecteur est présent
      const fontSizeSelect = page.locator('#fontSize')
      await expect(fontSizeSelect).toBeVisible()
    })

    test('devrait pouvoir changer la taille de police', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/profile')
      
      // Scroll vers la section display settings
      await page.getByText(/display settings/i).scrollIntoViewIfNeeded()
      
      // Cliquer sur le sélecteur
      const fontSizeSelect = page.locator('#fontSize')
      await fontSizeSelect.click()
      
      // Sélectionner une taille (ex: large)
      await page.getByRole('option', { name: /large/i }).click()
      
      // Vérifier qu'un toast de succès apparaît
      await expect(page.getByText(/success/i)).toBeVisible({ timeout: 3000 })
      
      // Vérifier que la taille de police a changé (vérifier la variable CSS)
      const rootFontSize = await page.evaluate(() => {
        return getComputedStyle(document.documentElement).getPropertyValue('--user-font-size')
      })
      expect(rootFontSize).toBeTruthy()
    })

    test('devrait avoir le toggle Show Recent Notes', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/profile')
      
      // Scroll vers la section display settings
      await page.getByText(/display settings/i).scrollIntoViewIfNeeded()
      
      // Vérifier que le toggle est présent
      const recentNotesToggle = page.getByRole('switch', { name: /show recent notes/i })
      await expect(recentNotesToggle).toBeVisible()
    })

    test('devrait pouvoir activer/désactiver Show Recent Notes', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/profile')
      
      // Scroll vers la section display settings
      await page.getByText(/display settings/i).scrollIntoViewIfNeeded()
      
      // Récupérer l'état initial du toggle
      const recentNotesToggle = page.getByRole('switch', { name: /show recent notes/i })
      const initialState = await recentNotesToggle.getAttribute('aria-checked')
      const initialEnabled = initialState === 'true'
      
      // Cliquer sur le toggle
      await recentNotesToggle.click()
      
      // Attendre un peu pour l'opération asynchrone
      await page.waitForTimeout(500)
      
      // Vérifier que l'état a changé
      const newState = await recentNotesToggle.getAttribute('aria-checked')
      const newEnabled = newState === 'true'
      expect(newEnabled).toBe(!initialEnabled)
      
      // Vérifier qu'un toast de succès apparaît
      await expect(page.getByText(/success/i)).toBeVisible({ timeout: 3000 })
    })

    test('devrait pouvoir changer le nom d\'affichage', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/profile')
      
      // Remplir le champ nom
      const nameInput = page.getByLabel(/display name/i)
      const newName = 'Test User ' + Date.now()
      await nameInput.fill(newName)
      
      // Soumettre le formulaire
      await page.getByRole('button', { name: /save/i }).click()
      
      // Vérifier qu'un toast de succès apparaît
      await expect(page.getByText(/success/i)).toBeVisible({ timeout: 3000 })
      
      // Recharger la page et vérifier que le nom a été sauvegardé
      await page.reload()
      await expect(nameInput).toHaveValue(newName)
    })
  })

  /**
   * Tests pour Appearance Settings
   */
  test.describe('Appearance Settings', () => {
    test('devrait afficher la page Appearance Settings', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/appearance')
      
      // Vérifier le titre de la page
      const title = await page.textContent('h1')
      expect(title).toContain('Appearance')
      
      // Vérifier les sections
      await expect(page.getByText(/theme/i)).toBeVisible()
      await expect(page.getByText(/typography/i)).toBeVisible()
    })

    test('devrait avoir le sélecteur de thème', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/appearance')
      
      // Vérifier que le sélecteur est présent
      const themeSelect = page.locator('#theme')
      await expect(themeSelect).toBeVisible()
    })

    test('devrait pouvoir changer le thème pour Light', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/appearance')
      
      // Cliquer sur le sélecteur de thème
      const themeSelect = page.locator('#theme')
      await themeSelect.click()
      
      // Sélectionner "Light"
      await page.getByRole('option', { name: /light/i }).click()
      
      // Vérifier que le thème est appliqué immédiatement
      await expect(page.locator('html')).toHaveClass(/light/)
      await expect(page.locator('html')).not.toHaveClass(/dark/)
      
      // Vérifier qu'un toast de succès apparaît
      await expect(page.getByText(/success/i)).toBeVisible({ timeout: 3000 })
      
      // Vérifier que le thème est sauvegardé dans localStorage
      const localStorageTheme = await page.evaluate(() => {
        return localStorage.getItem('theme')
      })
      expect(localStorageTheme).toBe('light')
    })

    test('devrait pouvoir changer le thème pour Dark', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/appearance')
      
      // Cliquer sur le sélecteur de thème
      const themeSelect = page.locator('#theme')
      await themeSelect.click()
      
      // Sélectionner "Dark"
      await page.getByRole('option', { name: /dark/i }).click()
      
      // Vérifier que le thème est appliqué immédiatement
      await expect(page.locator('html')).toHaveClass(/dark/)
      await expect(page.locator('html')).not.toHaveClass(/light/)
      
      // Vérifier qu'un toast de succès apparaît
      await expect(page.getByText(/success/i)).toBeVisible({ timeout: 3000 })
      
      // Vérifier que le thème est sauvegardé dans localStorage
      const localStorageTheme = await page.evaluate(() => {
        return localStorage.getItem('theme')
      })
      expect(localStorageTheme).toBe('dark')
    })

    test('devrait pouvoir changer le thème pour Auto', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/appearance')
      
      // Cliquer sur le sélecteur de thème
      const themeSelect = page.locator('#theme')
      await themeSelect.click()
      
      // Sélectionner "Auto"
      await page.getByRole('option', { name: /auto/i }).click()
      
      // Vérifier qu'un toast de succès apparaît
      await expect(page.getByText(/success/i)).toBeVisible({ timeout: 3000 })
      
      // Vérifier que le thème est sauvegardé dans localStorage
      const localStorageTheme = await page.evaluate(() => {
        return localStorage.getItem('theme')
      })
      expect(localStorageTheme).toBe('auto')
    })

    test('devrait charger le thème depuis localStorage', async ({ page }) => {
      // Définir le thème dans localStorage avant de charger la page
      await page.goto('about:blank')
      await page.evaluate(() => {
        localStorage.setItem('theme', 'dark')
      })
      
      // Aller sur la page Appearance Settings
      await page.goto('http://localhost:3000/settings/appearance')
      
      // Attendre que la page charge
      await page.waitForLoadState('networkidle')
      
      // Vérifier que le thème est chargé et appliqué
      const themeSelect = page.locator('#theme')
      await expect(themeSelect).toHaveValue('dark')
      
      // Vérifier que le thème est appliqué au DOM
      await expect(page.locator('html')).toHaveClass(/dark/)
    })

    test('devrait persister le thème après rechargement de page', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/appearance')
      
      // Changer le thème pour dark
      const themeSelect = page.locator('#theme')
      await themeSelect.click()
      await page.getByRole('option', { name: /dark/i }).click()
      
      // Attendre que le thème soit appliqué
      await expect(page.locator('html')).toHaveClass(/dark/)
      
      // Recharger la page
      await page.reload()
      await page.waitForLoadState('networkidle')
      
      // Vérifier que le thème est toujours appliqué
      await expect(page.locator('html')).toHaveClass(/dark/)
      await expect(themeSelect).toHaveValue('dark')
    })
  })

  /**
   * Tests d'intégration cross-pages
   */
  test.describe('Integration Tests', () => {
    test('devrait naviguer entre les pages de settings', async ({ page }) => {
      // Commencer sur General Settings
      await page.goto('http://localhost:3000/settings/general')
      
      // Cliquer sur Appearance dans la navigation
      await page.getByRole('link', { name: /appearance/i }).click()
      await expect(page).toHaveURL(/\/settings\/appearance/)
      
      // Cliquer sur Profile dans la navigation
      await page.getByRole('link', { name: /profile/i }).click()
      await expect(page).toHaveURL(/\/settings\/profile/)
      
      // Cliquer sur General dans la navigation
      await page.getByRole('link', { name: /general/i }).click()
      await expect(page).toHaveURL(/\/settings\/general/)
    })

    test('devrait persister les settings entre les pages', async ({ page }) => {
      // Changer le thème sur Appearance Settings
      await page.goto('http://localhost:3000/settings/appearance')
      const themeSelect = page.locator('#theme')
      await themeSelect.click()
      await page.getByRole('option', { name: /dark/i }).click()
      await expect(page.locator('html')).toHaveClass(/dark/)
      
      // Aller sur General Settings et vérifier que le thème est toujours appliqué
      await page.goto('http://localhost:3000/settings/general')
      await expect(page.locator('html')).toHaveClass(/dark/)
      
      // Aller sur Profile Settings et vérifier que le thème est toujours appliqué
      await page.goto('http://localhost:3000/settings/profile')
      await expect(page.locator('html')).toHaveClass(/dark/)
    })
  })

  /**
   * Tests de responsive design
   */
  test.describe('Responsive Design', () => {
    test('devrait fonctionner sur mobile', async ({ page }) => {
      // Simuler un viewport mobile
      await page.setViewportSize({ width: 375, height: 667 })
      
      await page.goto('http://localhost:3000/settings/general')
      
      // Vérifier que la page est utilisable
      await expect(page.locator('h1')).toBeVisible()
      await expect(page.getByPlaceholder(/search/i)).toBeVisible()
    })

    test('devrait fonctionner sur tablet', async ({ page }) => {
      // Simuler un viewport tablet
      await page.setViewportSize({ width: 768, height: 1024 })
      
      await page.goto('http://localhost:3000/settings/general')
      
      // Vérifier que la page est utilisable
      await expect(page.locator('h1')).toBeVisible()
      await expect(page.getByPlaceholder(/search/i)).toBeVisible()
    })

    test('devrait fonctionner sur desktop', async ({ page }) => {
      // Simuler un viewport desktop
      await page.setViewportSize({ width: 1280, height: 800 })
      
      await page.goto('http://localhost:3000/settings/general')
      
      // Vérifier que la page est utilisable
      await expect(page.locator('h1')).toBeVisible()
      await expect(page.getByPlaceholder(/search/i)).toBeVisible()
    })
  })

  /**
   * Tests de performance
   */
  test.describe('Performance Tests', () => {
    test('devrait charger rapidement General Settings', async ({ page }) => {
      const startTime = Date.now()
      await page.goto('http://localhost:3000/settings/general')
      await page.waitForLoadState('networkidle')
      const loadTime = Date.now() - startTime
      
      // La page devrait charger en moins de 2 secondes
      expect(loadTime).toBeLessThan(2000)
    })

    test('devrait appliquer le thème rapidement', async ({ page }) => {
      await page.goto('http://localhost:3000/settings/appearance')
      
      const themeSelect = page.locator('#theme')
      const startTime = Date.now()
      await themeSelect.click()
      await page.getByRole('option', { name: /dark/i }).click()
      await page.waitForSelector('html.dark', { timeout: 1000 })
      const applyTime = Date.now() - startTime
      
      // Le thème devrait être appliqué en moins de 500ms
      expect(applyTime).toBeLessThan(500)
    })
  })
})
