import { test, expect, type Page } from './fixtures';

// Network-level mocks for the private-mode UX. The backend integration
// tests (api_private_mode.rs) cover the actual gate; here we only
// verify that the SvelteKit universal load redirects anonymous
// visitors to /login and then back to where they were going.

const userFixture = {
    id: 'user-1',
    username: 'alice',
    created_at: '2026-01-01T00:00:00Z',
    is_admin: false
};
const emptyPage = { items: [], page: { limit: 50, offset: 0, total: null } };

async function stubPrivateInstance(page: Page) {
    let loggedIn = false;

    // The flag that flips the gate on. Frontend reads it in
    // `+layout.ts` to decide whether to redirect.
    await page.route('**/api/v1/auth/config', async (route) => {
        await route.fulfill({
            status: 200,
            contentType: 'application/json',
            body: JSON.stringify({
                self_register_enabled: false,
                private_mode: true
            })
        });
    });

    await page.route('**/api/v1/auth/me', async (route) => {
        if (loggedIn) {
            await route.fulfill({
                status: 200,
                contentType: 'application/json',
                body: JSON.stringify({ user: userFixture })
            });
        } else {
            await route.fulfill({
                status: 401,
                contentType: 'application/json',
                body: JSON.stringify({
                    error: { code: 'unauthenticated', message: 'unauthenticated' }
                })
            });
        }
    });

    await page.route('**/api/v1/auth/login', async (route) => {
        loggedIn = true;
        await route.fulfill({
            status: 200,
            contentType: 'application/json',
            body: JSON.stringify({ user: userFixture })
        });
    });

    // The real backend would 401 these too in private mode; we stub
    // success so the post-login navigation can render the home page
    // without an additional redirect cycle.
    await page.route('**/api/v1/mangas*', async (route) => {
        await route.fulfill({
            status: 200,
            contentType: 'application/json',
            body: JSON.stringify(emptyPage)
        });
    });
}

test('private mode: anonymous visit to / redirects to /login?next=%2F', async ({ page }) => {
    await stubPrivateInstance(page);
    await page.goto('/');
    await expect(page).toHaveURL(/\/login\?next=%2F$/);
    await expect(page.getByTestId('login-username')).toBeVisible();
});

test('private mode: register link is hidden', async ({ page }) => {
    await stubPrivateInstance(page);
    await page.goto('/login');
    await expect(page.getByTestId('nav-login')).toBeVisible();
    // self_register_enabled is the effective value (false in private
    // mode regardless of ALLOW_SELF_REGISTER), so the navbar must
    // never render the register affordance here.
    await expect(page.getByTestId('nav-register')).toHaveCount(0);
});

test('private mode: after login the user lands back on the requested page', async ({ page }) => {
    await stubPrivateInstance(page);

    // Visit a deep link → bounced to /login with next= preserving it.
    await page.goto('/');
    await expect(page).toHaveURL(/\/login\?next=%2F$/);

    await page.getByTestId('login-username').fill('alice');
    await page.getByTestId('login-password').fill('hunter2hunter2');
    await page.getByTestId('login-submit').click();

    // Authenticated → can now reach the home page without bouncing.
    await expect(page.getByTestId('session-user')).toContainText('alice');
});
