import { test as base, type Locator, 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_PROJECT = {
	id: "00000000-0000-0000-0000-000000000002",
	owner_id: "00000000-0000-0000-0000-000000000001",
	name: "Тестовый проект",
	description: null,
	language: "auto",
	folder: null,
	status: "DRAFT",
	workspace_state: null,
	is_active: true,
	created_at: "2025-06-01T00:00:00Z",
	updated_at: "2025-06-01T00:00:00Z",
}

interface ProjectsPage {
	page: Page
	/** Locator for the modal dialog (aria-modal prevents getByRole from working) */
	modal: Locator
	openCreateModal(): Promise<void>
	mockCreateSuccess(overrides?: Record<string, unknown>): Promise<void>
	mockCreateError(status: number, body?: Record<string, unknown>): Promise<void>
	mockCreateNetworkError(): Promise<void>
	mockCreateDelayed(ms?: number): Promise<void>
}

export const test = base.extend<{ projectsPage: ProjectsPage }>({
	projectsPage: async ({ page }, use) => {
		let projectsList: Record<string, unknown>[] = []

		// Set auth cookies
		await page.context().addCookies([
			{
				name: "access_token",
				value: "fake-access-jwt",
				domain: "localhost",
				path: "/",
			},
			{
				name: "refresh_token",
				value: "fake-refresh-jwt",
				domain: "localhost",
				path: "/",
			},
		])

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

		// Mock GET /api/projects/ (stateful)
		await page.route("**/api/projects/*", async (route: Route) => {
			if (route.request().method() === "GET") {
				await route.fulfill({
					status: 200,
					contentType: "application/json",
					body: JSON.stringify(projectsList),
				})
			} else {
				await route.fallback()
			}
		})

		await page.route("**/api/projects/", async (route: Route) => {
			if (route.request().method() === "GET") {
				await route.fulfill({
					status: 200,
					contentType: "application/json",
					body: JSON.stringify(projectsList),
				})
			} else {
				await route.fallback()
			}
		})

		await page.goto("/projects")
		await page.getByRole("heading", { name: "Мои проекты" }).waitFor()

		const modal = page.locator("[role=dialog]")

		const projectsPage: ProjectsPage = {
			page,
			modal,

			async openCreateModal() {
				await page.getByRole("button", { name: /Создать проект/ }).click()
				await modal.waitFor({ state: "visible" })
			},

			async mockCreateSuccess(overrides?: Record<string, unknown>) {
				const project = { ...DEFAULT_PROJECT, ...overrides }

				await page.route("**/api/projects/", async (route: Route) => {
					if (route.request().method() === "POST") {
						projectsList.push(project)
						await route.fulfill({
							status: 201,
							contentType: "application/json",
							body: JSON.stringify(project),
						})
					} else {
						await route.fallback()
					}
				})
			},

			async mockCreateError(
				status: number,
				body?: Record<string, unknown>,
			) {
				await page.route("**/api/projects/", async (route: Route) => {
					if (route.request().method() === "POST") {
						await route.fulfill({
							status,
							contentType: "application/json",
							body: JSON.stringify(body ?? { detail: "Server error" }),
						})
					} else {
						await route.fallback()
					}
				})
			},

			async mockCreateNetworkError() {
				await page.route("**/api/projects/", async (route: Route) => {
					if (route.request().method() === "POST") {
						await route.abort()
					} else {
						await route.fallback()
					}
				})
			},

			async mockCreateDelayed(ms = 2000) {
				const project = { ...DEFAULT_PROJECT }

				await page.route("**/api/projects/", async (route: Route) => {
					if (route.request().method() === "POST") {
						await new Promise((r) => setTimeout(r, ms))
						projectsList.push(project)
						await route.fulfill({
							status: 201,
							contentType: "application/json",
							body: JSON.stringify(project),
						})
					} else {
						await route.fallback()
					}
				})
			},
		}

		await use(projectsPage)
	},
})

export { expect } from "@playwright/test"
