import { beforeEach, describe, it, expect, vi } from 'vitest';
import { createPinia, setActivePinia } from 'pinia';

// Мокаем api/auth, чтобы router beforeEach guard не делал реальных HTTP-вызовов.
// `me()` возвращает AuthUser напрямую (см. resources/js/api/auth.ts:65-68).
vi.mock('../../resources/js/api/auth', () => ({
    me: vi.fn(() => Promise.reject(new Error('not authenticated'))),
    login: vi.fn(),
    register: vi.fn(),
    logout: vi.fn(),
}));

import { router } from '../../resources/js/router';
import { useAuthStore } from '../../resources/js/stores/auth';

describe('router/index.ts', () => {
    beforeEach(() => {
        setActivePinia(createPinia());
    });

    it('содержит маршрут /login с layout=auth + guestOnly', () => {
        const loginRoute = router.getRoutes().find((r) => r.name === 'login');
        expect(loginRoute).toBeDefined();
        expect(loginRoute?.path).toBe('/login');
        expect(loginRoute?.meta.layout).toBe('auth');
        expect(loginRoute?.meta.guestOnly).toBe(true);
    });

    it('защищённые маршруты помечены requiresAuth=true', () => {
        const protectedNames = ['dashboard', 'deals', 'kanban', 'billing', 'settings', 'reports'];
        const routes = router.getRoutes();
        protectedNames.forEach((name) => {
            const route = routes.find((r) => r.name === name);
            expect(route, `route ${name} not found`).toBeDefined();
            expect(route?.meta.requiresAuth, `route ${name} should require auth`).toBe(true);
        });
    });

    it('admin-маршруты помечены requiresAuth=true и layout=admin', () => {
        const routes = router.getRoutes();
        const adminTenants = routes.find((r) => r.name === 'admin-tenants');
        expect(adminTenants?.meta.requiresAuth).toBe(true);
        expect(adminTenants?.meta.layout).toBe('admin');
    });

    it('error-маршруты НЕ требуют auth', () => {
        const routes = router.getRoutes();
        const errorNames = ['forbidden', 'server-error', 'not-found'];
        errorNames.forEach((name) => {
            const route = routes.find((r) => r.name === name);
            expect(route?.meta.requiresAuth).toBeUndefined();
            expect(route?.meta.layout).toBe('error');
        });
    });

    it('гость, идущий на /dashboard без auth, редиректится на /login', async () => {
        await router.push('/dashboard');
        await router.isReady();
        // beforeEach guard делает fetchMe (мок отвергает) → user=null → redirect /login.
        expect(router.currentRoute.value.path).toBe('/login');
        // Сохраняется ?redirect=/dashboard для возврата после login.
        expect(router.currentRoute.value.query.redirect).toBe('/dashboard');
    });

    // ---------- Integration tests (Q.DEFER.003 sub-C) ----------
    // Покрывают actual navigation flows через beforeEach guard.
    // NB: `authInitialized` (router/index.ts:281) — module-level флаг, после первого
    // теста выше остаётся true. Тесты ниже устанавливают auth.user напрямую через
    // store mutation (bypass fetchMe path).

    it('authenticated user attempting /login (guestOnly) → redirected to /dashboard', async () => {
        const auth = useAuthStore();
        auth.user = {
            id: 1,
            email: 'test@demo.local',
            first_name: 'Test',
            last_name: 'User',
            tenant_id: 1,
            totp_enabled: false,
            last_login_at: '2026-05-13T00:00:00Z',
        } as unknown as ReturnType<typeof useAuthStore>['user'];
        await router.push('/login');
        await router.isReady();
        expect(router.currentRoute.value.path).toBe('/dashboard');
    });

    it('authenticated user navigating to /dashboard passes requiresAuth guard', async () => {
        const auth = useAuthStore();
        auth.user = {
            id: 1,
            email: 'test@demo.local',
            first_name: 'Test',
            last_name: 'User',
            tenant_id: 1,
            totp_enabled: false,
            last_login_at: '2026-05-13T00:00:00Z',
        } as unknown as ReturnType<typeof useAuthStore>['user'];
        await router.push('/dashboard');
        await router.isReady();
        expect(router.currentRoute.value.path).toBe('/dashboard');
        expect(router.currentRoute.value.name).toBe('dashboard');
    });

    it('unknown path /no-such-path resolves to 404 ErrorView', async () => {
        await router.push('/no-such-path-xyz');
        await router.isReady();
        expect(router.currentRoute.value.name).toBe('not-found');
        expect(router.currentRoute.value.meta.errorCode).toBe('404');
        expect(router.currentRoute.value.meta.layout).toBe('error');
    });

    it('/admin redirects to /admin/dashboard', async () => {
        const auth = useAuthStore();
        auth.user = {
            id: 1,
            email: 'test@demo.local',
            first_name: 'Test',
            last_name: 'User',
            tenant_id: 1,
            totp_enabled: false,
            last_login_at: '2026-05-13T00:00:00Z',
        } as unknown as ReturnType<typeof useAuthStore>['user'];
        await router.push('/admin');
        await router.isReady();
        expect(router.currentRoute.value.path).toBe('/admin/dashboard');
        expect(router.currentRoute.value.name).toBe('admin-dashboard');
    });

    it('/reset/:token resolves with token param exposed', async () => {
        // auth.user остаётся null (beforeEach создал свежий Pinia), guestOnly пропускает.
        await router.push('/reset/abc123-token-xyz');
        await router.isReady();
        expect(router.currentRoute.value.name).toBe('reset-password');
        expect(router.currentRoute.value.params.token).toBe('abc123-token-xyz');
    });

    it('маршрут /import зарегистрирован с layout app', () => {
        const importRoute = router.getRoutes().find((r) => r.name === 'import');
        expect(importRoute, 'route import not found').toBeDefined();
        expect(importRoute?.path).toBe('/import');
        expect(importRoute?.meta.layout).toBe('app');
        expect(importRoute?.meta.requiresAuth).toBe(true);
    });
});
