"""页面上下文管理（多标签页支持）"""

from playwright.sync_api import Page, BrowserContext
from typing import Optional, List, Dict, Callable
from ..reference import GSTORE, PRIVATEDATA, INFO


class PageContext:
    """页面上下文管理器

    管理多标签页，支持页面切换、新页面监听等功能。
    """

    def __init__(self, context: Optional[BrowserContext] = None):
        """初始化页面上下文管理器

        Args:
            context: BrowserContext 实例，如果不提供则从 GSTORE 获取
        """
        self._context = context or GSTORE.get('context')
        self._pages: List[Page] = []
        self._current_index: int = 0
        self._page_handlers: Dict[str, Callable] = {}

        if self._context:
            # 初始化已有页面
            self._pages = list(self._context.pages)

            # 监听新页面
            self._context.on('page', self._on_new_page)

    def _on_new_page(self, page: Page) -> None:
        """新页面事件处理

        Args:
            page: 新打开的页面
        """
        self._pages.append(page)
        INFO(f"检测到新页面: {page.url}")

        # 执行注册的处理器
        for handler in self._page_handlers.values():
            try:
                handler(page)
            except Exception as e:
                INFO(f"页面处理器执行失败: {e}", "ERROR")

    @property
    def current_page(self) -> Optional[Page]:
        """获取当前活动页面"""
        if not self._pages:
            return GSTORE.get('page')
        return self._pages[self._current_index]

    @property
    def page_count(self) -> int:
        """获取页面数量"""
        return len(self._pages)

    @property
    def pages(self) -> List[Page]:
        """获取所有页面"""
        return self._pages.copy()

    def switch_to_page(self, index: int) -> Page:
        """切换到指定索引的页面

        Args:
            index: 页面索引 (支持负数索引)

        Returns:
            Page: 切换后的页面

        Raises:
            IndexError: 索引超出范围
        """
        if not self._pages:
            raise IndexError("没有可用的页面")

        # 处理负数索引
        if index < 0:
            index = len(self._pages) + index

        if index < 0 or index >= len(self._pages):
            raise IndexError(f"页面索引超出范围: {index}")

        self._current_index = index
        page = self._pages[index]

        # 更新全局存储
        GSTORE['page'] = page
        PRIVATEDATA['PAGES'] = self._pages

        INFO(f"切换到页面 {index}: {page.url}")
        return page

    def switch_to_new_page(self, timeout: int = 30000) -> Page:
        """等待并切换到新打开的页面

        Args:
            timeout: 等待超时 (毫秒)

        Returns:
            Page: 新页面
        """
        if not self._context:
            raise RuntimeError("浏览器上下文未初始化")

        with self._context.expect_page(timeout=timeout) as new_page_info:
            pass

        new_page = new_page_info.value
        new_page.wait_for_load_state('domcontentloaded')

        # 更新页面列表
        if new_page not in self._pages:
            self._pages.append(new_page)

        self._current_index = len(self._pages) - 1
        GSTORE['page'] = new_page

        INFO(f"切换到新页面: {new_page.url}")
        return new_page

    def switch_to_page_by_url(self, url_pattern: str) -> Optional[Page]:
        """根据 URL 模式切换页面

        Args:
            url_pattern: URL 匹配模式 (支持部分匹配)

        Returns:
            Page: 匹配的页面，未找到返回 None
        """
        for i, page in enumerate(self._pages):
            if url_pattern in page.url:
                return self.switch_to_page(i)

        INFO(f"未找到匹配的页面: {url_pattern}", "WARNING")
        return None

    def switch_to_page_by_title(self, title_pattern: str) -> Optional[Page]:
        """根据标题模式切换页面

        Args:
            title_pattern: 标题匹配模式 (支持部分匹配)

        Returns:
            Page: 匹配的页面，未找到返回 None
        """
        for i, page in enumerate(self._pages):
            if title_pattern in page.title():
                return self.switch_to_page(i)

        INFO(f"未找到匹配的页面: {title_pattern}", "WARNING")
        return None

    def close_current_page(self) -> Optional[Page]:
        """关闭当前页面并切换到上一个页面

        Returns:
            Page: 切换后的当前页面，如果没有其他页面返回 None
        """
        if not self._pages:
            return None

        current = self._pages[self._current_index]
        current.close()
        self._pages.pop(self._current_index)

        if not self._pages:
            GSTORE['page'] = None
            return None

        # 切换到上一个页面
        if self._current_index >= len(self._pages):
            self._current_index = len(self._pages) - 1

        new_current = self._pages[self._current_index]
        GSTORE['page'] = new_current

        INFO(f"关闭页面，切换到: {new_current.url}")
        return new_current

    def close_page(self, index: int) -> None:
        """关闭指定索引的页面

        Args:
            index: 页面索引
        """
        if index < 0 or index >= len(self._pages):
            raise IndexError(f"页面索引超出范围: {index}")

        page = self._pages[index]
        page.close()
        self._pages.pop(index)

        # 调整当前索引
        if self._current_index >= len(self._pages):
            self._current_index = max(0, len(self._pages) - 1)

        if self._pages:
            GSTORE['page'] = self._pages[self._current_index]
        else:
            GSTORE['page'] = None

    def register_page_handler(self, name: str, handler: Callable[[Page], None]) -> None:
        """注册新页面处理器

        Args:
            name: 处理器名称
            handler: 处理函数，接收 Page 参数
        """
        self._page_handlers[name] = handler

    def unregister_page_handler(self, name: str) -> None:
        """注销页面处理器

        Args:
            name: 处理器名称
        """
        self._page_handlers.pop(name, None)

    def refresh(self) -> None:
        """刷新页面列表（同步上下文中的页面）"""
        if self._context:
            self._pages = list(self._context.pages)
            if self._pages and self._current_index >= len(self._pages):
                self._current_index = len(self._pages) - 1
