import { expect, test } from '@playwright/test'
import { loginAs } from '../helpers/loginAs'
import { SidebarComponent } from '../helpers/pages/SidebarComponent'
import { ALL_ADMIN_LINKS, type PersonaKey, getPersona, personas } from '../_fixtures/personas'

/**
 * Test strategique : la matrice persona <-> liens admin visibles.
 *
 * Valide que `SidebarProvider` (back) + `useSidebar` (front) filtrent bien
 * les items admin selon les permissions RBAC de chaque user.
 *
 * Regle d'evolution : ajouter une permission ou un persona = 1 ligne a
 * modifier dans `personas.ts` et cote back (`SeedE2ECommand`) + `sidebar.php`.
 * Ce fichier ne bouge pas.
 */
test.describe('Sidebar visibility', () => {
    const personaKeys: PersonaKey[] = [
        'super-admin',
        'user-full',
        'user-readonly',
        'user-users-only',
        'user-audit-only',
        'user-nothing',
    ]

    for (const key of personaKeys) {
        const persona = getPersona(key)

        test(`${persona.key} ne voit que ses liens admin autorises`, async ({ page, context }) => {
            await loginAs(context, persona.key)
            await page.goto('/')

            const sidebar = new SidebarComponent(page)

            // Attente semantique : on ancre sur un lien toujours present pour
            // tout user authentifie (Mon compte > Tableau de bord). Remplace
            // `networkidle` qui est reconnu instable en CI (SPAs avec polling
            // ou HMR peuvent ne jamais quitter cet etat).
            await expect(sidebar.accountDashboardLink()).toBeVisible({ timeout: 10000 })

            for (const link of ALL_ADMIN_LINKS) {
                const locator = sidebar.adminLink(link)
                const shouldBeVisible = persona.expectedAdminLinks.includes(link)

                if (shouldBeVisible) {
                    await expect(
                        locator,
                        `${persona.key} doit voir le lien /admin/${link}`,
                    ).toBeVisible()
                } else {
                    await expect(
                        locator,
                        `${persona.key} ne doit PAS voir le lien /admin/${link}`,
                    ).toHaveCount(0)
                }
            }
        })
    }

    test('user-nothing voit toujours le dashboard et le logout (section Mon compte sans permission)', async ({
        page,
        context,
    }) => {
        // La section "Mon compte" n'est gardee par aucune permission : tout user
        // authentifie voit le dashboard et peut se deconnecter. Ce test protege
        // contre une regression qui mettrait un gate RBAC par inadvertance
        // dessus — ca bloquerait le logout de users sans permissions.
        await loginAs(context, 'user-nothing')
        await page.goto('/')

        const sidebar = new SidebarComponent(page)
        // Meme strategie que ci-dessus : ancrage semantique plutot que
        // `networkidle` pour eviter les faux timeouts en CI.
        await expect(sidebar.accountDashboardLink()).toBeVisible({ timeout: 10000 })
        await expect(sidebar.logoutLink()).toBeVisible()
    })

    test('la liste des personas dans personas.ts couvre toutes les combinaisons admin attendues', () => {
        // Test meta : si quelqu'un ajoute un persona dans personas.ts sans le
        // seeder cote back (SeedE2ECommand), le test sidebar pour ce persona
        // echouera (loginAs 401). Ce test rappelle la coherence attendue.
        expect(Object.keys(personas)).toEqual(personaKeys)
    })
})
