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

const userFixture = {
    id: 'u1',
    username: 'alice',
    created_at: '2026-01-01T00:00:00Z'
};

const baseManga = {
    id: 'm1',
    title: 'Berserk',
    status: 'ongoing',
    alt_titles: ['Old Alt'],
    description: 'Original description',
    cover_image_path: null,
    created_at: '2026-01-01T00:00:00Z',
    updated_at: '2026-01-01T00:00:00Z',
    authors: [{ id: 'a1', name: 'Kentaro Miura' }],
    genres: [],
    tags: []
};

async function stubAuthenticatedAndGenres(page: Page) {
    await page.route('**/api/v1/auth/me', (route) =>
        route.fulfill({
            status: 200,
            contentType: 'application/json',
            body: JSON.stringify({ user: userFixture })
        })
    );
    await page.route('**/api/v1/genres', (route) =>
        route.fulfill({
            status: 200,
            contentType: 'application/json',
            body: JSON.stringify([
                { id: 'g-action', name: 'Action' },
                { id: 'g-fantasy', name: 'Fantasy' }
            ])
        })
    );
}

test('anonymous user sees sign-in prompt on /manga/[id]/edit', async ({ page }) => {
    await page.route('**/api/v1/auth/me', (route) =>
        route.fulfill({
            status: 401,
            contentType: 'application/json',
            body: JSON.stringify({
                error: { code: 'unauthenticated', message: 'unauthenticated' }
            })
        })
    );
    await page.route('**/api/v1/genres', (route) =>
        route.fulfill({ status: 200, contentType: 'application/json', body: '[]' })
    );
    await page.route('**/api/v1/mangas/m1', (route) =>
        route.fulfill({
            status: 200,
            contentType: 'application/json',
            body: JSON.stringify(baseManga)
        })
    );

    await page.goto('/manga/m1/edit');
    await expect(page.getByTestId('edit-signin')).toBeVisible();
});

test('/manga/[id]/edit PATCHes the changed metadata and lands on the manga page', async ({
    page
}) => {
    await stubAuthenticatedAndGenres(page);

    let patchBody: Record<string, unknown> | null = null;
    let mangaAfter = { ...baseManga };
    await page.route('**/api/v1/mangas/m1', async (route) => {
        const method = route.request().method();
        if (method === 'GET') {
            await route.fulfill({
                status: 200,
                contentType: 'application/json',
                body: JSON.stringify(mangaAfter)
            });
        } else if (method === 'PATCH') {
            patchBody = JSON.parse(route.request().postData() ?? '{}');
            mangaAfter = {
                ...mangaAfter,
                title: (patchBody.title as string) ?? mangaAfter.title,
                description:
                    'description' in (patchBody as Record<string, unknown>)
                        ? ((patchBody.description as string | null) ?? null)
                        : mangaAfter.description
            };
            await route.fulfill({
                status: 200,
                contentType: 'application/json',
                body: JSON.stringify(mangaAfter)
            });
        } else {
            await route.fallback();
        }
    });
    await page.route('**/api/v1/mangas/m1/chapters*', (route) =>
        route.fulfill({
            status: 200,
            contentType: 'application/json',
            body: JSON.stringify({
                items: [],
                page: { limit: 50, offset: 0, total: 0 }
            })
        })
    );
    await page.route('**/api/v1/me/bookmarks*', (route) =>
        route.fulfill({
            status: 200,
            contentType: 'application/json',
            body: JSON.stringify({
                items: [],
                page: { limit: 50, offset: 0, total: 0 }
            })
        })
    );
    await page.route('**/api/v1/me/read-progress/m1', (route) =>
        route.fulfill({
            status: 404,
            contentType: 'application/json',
            body: JSON.stringify({
                error: { code: 'not_found', message: 'no progress' }
            })
        })
    );

    await page.goto('/manga/m1');
    // Edit link is gated on session.user — it should be visible to the
    // stubbed authenticated user.
    await page.getByTestId('edit-manga-link').click();
    await expect(page).toHaveURL(/\/manga\/m1\/edit$/);

    const titleInput = page.getByTestId('manga-title');
    await expect(titleInput).toHaveValue('Berserk');
    await titleInput.fill('Berserk (Deluxe)');
    await page.getByTestId('manga-edit-submit').click();

    await expect(page).toHaveURL(/\/manga\/m1$/);
    await expect(page.getByTestId('manga-title')).toHaveText('Berserk (Deluxe)');
    expect(patchBody).not.toBeNull();
    expect((patchBody as Record<string, unknown>).title).toBe('Berserk (Deluxe)');
});
