import type { Page } from "@playwright/test"
import { test as base, expect as pwExpect } from "@playwright/test"
import { attachConsoleMonitor } from "../fixtures/console-monitor"

export { expect, type Page, API_BASE, clickSpaLink } from "../e2e/fixtures"
import { expect } from "../e2e/fixtures"

type MobileFixtures = {}

export const test = base.extend<MobileFixtures>({
    /**
     * Override page fixture: BrowserSync domcontentloaded workaround.
     */
    page: async ({ page }, use) => {
        const monitor = attachConsoleMonitor(page)

        const origGoto = page.goto.bind(page)
        const origReload = page.reload.bind(page)

        page.goto = ((url: string, opts?: any) =>
            origGoto(url, { waitUntil: "domcontentloaded", ...opts })) as typeof page.goto
        page.reload = ((opts?: any) => origReload({ waitUntil: "domcontentloaded", ...opts })) as typeof page.reload

        await use(page)
        monitor.assertNoErrors()
    },
})

/**
 * Wait for the SPA to be ready in mobile viewport.
 */
export async function waitForSpaReady(page: Page): Promise<string> {
    await page.waitForLoadState("domcontentloaded")
    await expect(page.locator("#appContainer")).not.toBeEmpty({ timeout: 15000 })
    const url = page.url()
    const match = url.match(/\/([a-z]{2})(\/|$)/)
    return match?.[1] || "de"
}

/**
 * Navigate to a route with language prefix.
 */
export async function navigateToRoute(page: Page, routePath: string): Promise<void> {
    const url = page.url()
    const match = url.match(/\/([a-z]{2})(\/|$)/)
    const lang = match?.[1] || "de"
    const fullPath = routePath === "/" ? `/${lang}` : `/${lang}${routePath}`
    await page.goto(fullPath, { waitUntil: "domcontentloaded" })
    await expect(page.locator("#appContainer")).not.toBeEmpty({ timeout: 15000 })
}

/** Check if viewport width is mobile (<768px) */
export function isMobileViewport(page: Page): boolean {
    return (page.viewportSize()?.width ?? 0) < 768
}

/** Check if viewport width is tablet (768-1023px) */
export function isTabletViewport(page: Page): boolean {
    const w = page.viewportSize()?.width ?? 0
    return w >= 768 && w < 1024
}

/** Check if viewport width is below lg breakpoint (<1024px) */
export function isBelowLg(page: Page): boolean {
    return (page.viewportSize()?.width ?? 0) < 1024
}

/**
 * Open the hamburger/mobile navigation menu.
 * Finds the first visible button with aria-expanded in the header.
 */
export async function openHamburgerMenu(page: Page): Promise<void> {
    const hamburgers = page.locator("header button[aria-expanded]")
    const count = await hamburgers.count()
    let clicked = false
    for (let i = 0; i < count; i++) {
        const btn = hamburgers.nth(i)
        if (await btn.isVisible()) {
            await btn.click()
            clicked = true
            break
        }
    }
    if (!clicked) {
        throw new Error("No visible hamburger button found in header")
    }
    await page.waitForTimeout(500)
    await page
        .waitForFunction(
            () => {
                const btn = document.querySelector<HTMLButtonElement>("header button[aria-expanded='true']")
                return btn !== null
            },
            { timeout: 5000 }
        )
        .catch(() => {})
}

/**
 * Close the hamburger menu via Escape key.
 */
export async function closeHamburgerMenuViaEscape(page: Page): Promise<void> {
    await page.keyboard.press("Escape")
    await page
        .waitForFunction(
            () => {
                const btn = document.querySelector<HTMLButtonElement>("header button[aria-expanded='true']")
                return btn === null
            },
            { timeout: 5000 }
        )
        .catch(() => {})
}
