"""
浏览器配置模块
提供跨浏览器测试的配置和工具函数
"""

from typing import Dict, List, Optional, Tuple
from dataclasses import dataclass
from enum import Enum

from playwright.sync_api import Browser, BrowserType, BrowserContext, Page
from playwright.sync_api import Error as PlaywrightError
from playwright.sync_api import sync_playwright

from config.settings import get_settings


class BrowserTypeEnum(Enum):
    """支持的浏览器类型"""
    CHROMIUM = "chromium"
    FIREFOX = "firefox"
    WEBKIT = "webkit"


@dataclass
class BrowserCapabilities:
    """浏览器能力描述"""
    name: str
    display_name: str
    channel: Optional[str]
    is_headless_supported: bool
    default_viewport: tuple
    user_agent: str
    description: str


class BrowserConfigManager:
    """浏览器配置管理器"""
    
    # 浏览器能力定义
    BROWSER_CAPABILITIES: Dict[str, BrowserCapabilities] = {
        "chromium": BrowserCapabilities(
            name="chromium",
            display_name="Chrome/Chromium",
            channel="chrome",
            is_headless_supported=True,
            default_viewport=(1920, 1080),
            user_agent=(
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
            ),
            description="Google Chrome / Chromium浏览器"
        ),
        "firefox": BrowserCapabilities(
            name="firefox",
            display_name="Firefox",
            channel=None,
            is_headless_supported=True,
            default_viewport=(1920, 1080),
            user_agent=(
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) "
                "Gecko/20100101 Firefox/121.0"
            ),
            description="Mozilla Firefox浏览器"
        ),
        "webkit": BrowserCapabilities(
            name="webkit",
            display_name="WebKit (Safari)",
            channel=None,
            is_headless_supported=True,
            default_viewport=(1920, 1080),
            user_agent=(
                "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_2) "
                "AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15"
            ),
            description="Apple WebKit (Safari)浏览器"
        )
    }
    
    def __init__(self):
        self.settings = get_settings()
        self._playwright: Optional[sync_playwright] = None
        self._browser: Optional[Browser] = None
        self._context: Optional[BrowserContext] = None
    
    def _ensure_playwright(self) -> sync_playwright:
        """确保Playwright实例已启动"""
        if self._playwright is None:
            self._playwright = sync_playwright().start()
        return self._playwright
    
    def get_available_browsers(self) -> List[str]:
        """获取可用的浏览器列表"""
        available = []
        p = self._ensure_playwright()
        
        browser_map = {
            "chromium": p.chromium,
            "firefox": p.firefox,
            "webkit": p.webkit
        }
        
        for name in browser_map:
            try:
                available.append(name)
            except Exception:
                continue
        
        return available
    
    def _get_browser_type(self, browser_name: str):
        """获取浏览器类型"""
        p = self._ensure_playwright()
        browser_map = {
            "chromium": p.chromium,
            "firefox": p.firefox,
            "webkit": p.webkit
        }
        return browser_map.get(browser_name)
    
    def launch_browser(
        self,
        browser_name: str = "chromium",
        headless: bool = False,
        viewport: Optional[Tuple[int, int]] = None,
        **kwargs
    ) -> Browser:
        """启动浏览器"""
        capabilities = self.BROWSER_CAPABILITIES.get(browser_name)
        if not capabilities:
            raise ValueError(f"不支持的浏览器类型: {browser_name}")
        
        viewport = viewport or (self.settings.viewport_width, self.settings.viewport_height)
        
        launch_args = self._get_launch_arguments(browser_name, headless)
        
        browser_type = self._get_browser_type(browser_name)
        if not browser_type:
            raise ValueError(f"不支持的浏览器类型: {browser_name}")
        
        self._browser = browser_type.launch(
            headless=headless,
            args=launch_args,
            **kwargs
        )
        
        return self._browser
    
    def _get_launch_arguments(self, browser_name: str, headless: bool) -> List[str]:
        """获取浏览器启动参数"""
        args = []
        
        if browser_name == "chromium":
            args.extend([
                "--disable-extensions",
                "--disable-background-networking",
                "--disable-sync",
                "--disable-translate",
                "--metrics-recording-only",
                "--mute-audio",
                "--no-first-run",
                "--safebrowsing-disable-auto-update",
                "--ignore-certificate-errors",
                "--ignore-ssl-errors",
                "--disable-dev-shm-usage",
            ])
            
            if headless:
                args.extend([
                    "--headless=new",
                    "--disable-gpu",
                    "--no-sandbox",
                ])
        
        elif browser_name == "firefox":
            if headless:
                args.extend(["-headless"])
            
            args.extend([
                "-profile",
                "/tmp/firefox-profile",
            ])
        
        elif browser_name == "webkit":
            if headless:
                args.append("--headless")
            
            args.extend([
                "--no-sandbox",
                "--disable-setuid-sandbox",
            ])
        
        return args
    
    def create_context(
        self,
        browser: Browser,
        viewport: Optional[Tuple[int, int]] = None,
        **context_kwargs
    ) -> BrowserContext:
        """创建浏览器上下文"""
        viewport = viewport or (self.settings.viewport_width, self.settings.viewport_height)
        
        capabilities = self.BROWSER_CAPABILITIES.get(
            browser.browser_type.name, 
            self.BROWSER_CAPABILITIES["chromium"]
        )
        
        context_options = {
            "viewport": {
                "width": viewport[0],
                "height": viewport[1]
            },
            "user_agent": capabilities.user_agent,
            "locale": "zh-CN",
            "timezone_id": "Asia/Shanghai",
            **context_kwargs
        }
        
        self._context = browser.new_context(**context_options)
        
        return self._context
    
    def create_browser_session(
        self,
        browser_name: str = "chromium",
        headless: bool = False,
        viewport: Optional[Tuple[int, int]] = None
    ) -> Tuple[Browser, BrowserContext, Page]:
        """创建完整的浏览器会话"""
        browser = self.launch_browser(browser_name, headless, viewport)
        context = self.create_context(browser, viewport)
        page = context.new_page()
        
        return browser, context, page
    
    def close_browser(self) -> None:
        """关闭浏览器和上下文"""
        if self._context:
            try:
                self._context.close()
            except Exception:
                pass
            self._context = None
        
        if self._browser:
            try:
                self._browser.close()
            except Exception:
                pass
            self._browser = None
        
        if self._playwright:
            try:
                self._playwright.stop()
            except Exception:
                pass
            self._playwright = None
    
    def __enter__(self) -> 'BrowserConfigManager':
        """上下文管理器入口"""
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb) -> None:
        """上下文管理器退出"""
        self.close_browser()


def get_browser_factory() -> BrowserConfigManager:
    """获取浏览器工厂实例"""
    return BrowserConfigManager()
