"""
Web 端根级 fixture：浏览器实例 + 失败自动截图。

提供:
    browser_name — 参数化 fixture，每个浏览器执行一轮
    page        — Playwright Page 对象（每个用例独立）
    login       — 可复用的登录 helper

Usage:
    def test_something(page, browser_name):
        page.goto("/admin")
        ...

    def test_admin_flow(page, login):
        login("super_admin")  # 以管理员身份登录
        ...
"""

from datetime import datetime
from pathlib import Path

import pytest
from playwright.sync_api import sync_playwright

# 截图根目录
SCREENSHOTS_DIR = Path("output/screenshots")


@pytest.fixture(scope="session")
def web_config(config):
    """session 级：Web 配置段。"""
    return config["web"]


@pytest.fixture(params=["chromium", "firefox"])
def browser_name(request):
    """每个浏览器执行一次同一套用例。"""
    return request.param


@pytest.fixture
def page(web_config, browser_name, request):
    """每个用例独立的 Playwright Page，失败自动截图。"""
    viewport = web_config.get("viewport", {"width": 1920, "height": 1080})
    timeout = web_config.get("timeout_seconds", 120) * 1000
    screenshot_on_failure = web_config.get("screenshot_on_failure", True)

    with sync_playwright() as p:
        browser_launcher = getattr(p, browser_name)
        browser = browser_launcher.launch(headless=True)
        context = browser.new_context(
            viewport={"width": viewport["width"], "height": viewport["height"]},
            locale="zh-CN",
        )
        page = context.new_page()
        page.set_default_timeout(timeout)

        yield page

        # ── 失败自动截图 ──
        if screenshot_on_failure and hasattr(request.node, "rep_call") and request.node.rep_call.failed:
            scenario_dir = SCREENSHOTS_DIR / request.node.name
            scenario_dir.mkdir(parents=True, exist_ok=True)
            ts = datetime.now().strftime("%Y%m%d_%H%M%S")
            path = str(scenario_dir / f"FAIL_{browser_name}_{ts}.png")
            page.screenshot(path=path, full_page=True)

        context.close()
        browser.close()


@pytest.fixture
def login(page, web_config, config):
    """返回一个登录 helper 函数，按角色名自动填入账号并等待登录完成。

    Usage:
        def test_admin(page, login):
            login("super_admin")
            page.getByTestId("nav-dashboard").click()
    """

    def _login(role: str = "super_admin") -> None:
        account = config["accounts"].get(role)
        if not account:
            raise ValueError(f"未知角色 '{role}'，可用: {list(config['accounts'].keys())}")

        base_url = web_config["base_url"]
        # 如果已经打开某个页面且未过期，直接返回
        if page.url and not page.url.startswith("about:") and "/login" not in page.url:
            return

        page.goto(f"{base_url}/login")
        page.getByPlaceholder("请输入用户名").fill(account["phone"])
        page.getByPlaceholder("请输入密码").fill(account["password"])
        page.getByRole("button", name="登录").click()

        # 等待登录成功跳转（10 秒超时）
        page.wait_for_url(f"{base_url}/**", timeout=10_000)

    return _login


# ── pytest 报告 hook：记录每个用例的失败状态 ──
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    """在每个用例执行后记录结果，供 fixture 中的失败截图逻辑使用。"""
    outcome = yield
    rep = outcome.get_result()
    setattr(item, f"rep_{rep.when}", rep)
