import { test as base, type Page, type Route } from "@playwright/test"

const DEFAULT_USER = {
	id: "00000000-0000-0000-0000-000000000001",
	username: "testuser",
	email: "test@example.com",
	first_name: "Test",
	last_name: "User",
	phone_number: null,
	avatar: null,
	email_verified: true,
	phone_verified: false,
	is_active: true,
	is_staff: false,
	is_superuser: false,
	date_joined: "2025-01-01T00:00:00Z",
}

const DEFAULT_TOKENS = {
	access: "fake-access-jwt",
	refresh: "fake-refresh-jwt",
}

interface LoginPage {
	page: Page
	login(username: string, password: string): Promise<void>
	mockLoginSuccess(userData?: Record<string, unknown>): Promise<void>
	mockLoginError(status: number, body?: Record<string, unknown>): Promise<void>
	mockLoginNetworkError(): Promise<void>
	mockLoginDelayed(delayMs?: number): Promise<void>
}

export const test = base.extend<{ loginPage: LoginPage }>({
	loginPage: async ({ page }, use) => {
		await page.goto("/login")
		await page.getByRole("heading", { name: "Вход" }).waitFor()

		const loginPage: LoginPage = {
			page,

			async login(username: string, password: string) {
				await page.getByRole("textbox", { name: "Логин" }).fill(username)
				await page.getByRole("textbox", { name: "Пароль" }).fill(password)
				await page.getByRole("button", { name: "Войти" }).click()
			},

			async mockLoginSuccess(userData?: Record<string, unknown>) {
				const mockUser = { ...DEFAULT_USER, ...userData }

				await page.route("**/auth/login", async (route: Route) => {
					await route.fulfill({
						status: 200,
						contentType: "application/json",
						body: JSON.stringify({
							user: mockUser,
							...DEFAULT_TOKENS,
						}),
					})
				})

				await page.route("**/api/users/me/", async (route: Route) => {
					await route.fulfill({
						status: 200,
						contentType: "application/json",
						body: JSON.stringify(mockUser),
					})
				})

				await page.route("**/api/projects/*", async (route: Route) => {
					await route.fulfill({
						status: 200,
						contentType: "application/json",
						body: JSON.stringify([]),
					})
				})
			},

			async mockLoginError(
				status: number,
				body?: Record<string, unknown>,
			) {
				await page.route("**/auth/login", async (route: Route) => {
					await route.fulfill({
						status,
						contentType: "application/json",
						body: JSON.stringify(
							body ?? { detail: "Invalid credentials" },
						),
					})
				})
			},

			async mockLoginNetworkError() {
				await page.route("**/auth/login", async (route: Route) => {
					await route.abort()
				})
			},

			async mockLoginDelayed(delayMs = 2000) {
				await page.route("**/auth/login", async (route: Route) => {
					await new Promise((r) => setTimeout(r, delayMs))
					await route.fulfill({
						status: 200,
						contentType: "application/json",
						body: JSON.stringify({
							user: DEFAULT_USER,
							...DEFAULT_TOKENS,
						}),
					})
				})
			},
		}

		await use(loginPage)
	},
})

export { expect } from "@playwright/test"
