"""
选择器增强模块
支持多种选择器类型和链式定位
"""
from typing import Optional, Union, List
from playwright.async_api import Page, Locator
from loguru import logger
from enum import Enum


class SelectorType(Enum):
    """选择器类型"""
    CSS = "css"           # CSS选择器
    XPATH = "xpath"       # XPath
    TEXT = "text"         # 文本匹配
    ROLE = "role"         # ARIA角色
    PLACEHOLDER = "placeholder"  # 占位符
    LABEL = "label"       # 标签
    TEST_ID = "test-id"   # 测试ID
    ALT_TEXT = "alt-text" # 图片alt文本
    TITLE = "title"       # title属性


class SmartSelector:
    """
    智能选择器
    支持多种选择器类型和链式定位
    """
    
    def __init__(self, page: Page):
        self.page = page
    
    def css(self, selector: str) -> Locator:
        """CSS选择器"""
        return self.page.locator(selector)
    
    def xpath(self, selector: str) -> Locator:
        """XPath选择器"""
        return self.page.locator(f"xpath={selector}")
    
    def text(self, text: str, exact: bool = False) -> Locator:
        """
        文本选择器
        
        Args:
            text: 要匹配的文本
            exact: 是否精确匹配
        """
        return self.page.get_by_text(text, exact=exact)
    
    def role(self, role: str, name: Optional[str] = None) -> Locator:
        """
        ARIA角色选择器
        
        Args:
            role: ARIA角色 (button, link, textbox, etc.)
            name: 可访问名称
        """
        return self.page.get_by_role(role, name=name)
    
    def placeholder(self, text: str) -> Locator:
        """占位符选择器"""
        return self.page.get_by_placeholder(text)
    
    def label(self, text: str) -> Locator:
        """标签选择器"""
        return self.page.get_by_label(text)
    
    def test_id(self, test_id: str) -> Locator:
        """测试ID选择器"""
        return self.page.get_by_test_id(test_id)
    
    def alt_text(self, text: str) -> Locator:
        """图片alt文本选择器"""
        return self.page.get_by_alt_text(text)
    
    def title(self, text: str) -> Locator:
        """title属性选择器"""
        return self.page.get_by_title(text)
    
    def chain(self, *selectors: str) -> Locator:
        """
        链式选择器
        
        Args:
            *selectors: 选择器链
            
        Returns:
            Locator: 链式定位结果
            
        Example:
            selector.chain("div.container", "ul.list", "li.item")
            等价于: page.locator("div.container >> ul.list >> li.item")
        """
        chain_str = " >> ".join(selectors)
        return self.page.locator(chain_str)
    
    def filter(
        self, 
        parent: str, 
        child: str,
        has_text: Optional[str] = None,
        has_not_text: Optional[str] = None,
    ) -> Locator:
        """
        过滤选择器
        
        Args:
            parent: 父元素选择器
            child: 子元素选择器
            has_text: 必须包含的文本
            has_not_text: 不能包含的文本
        """
        locator = self.page.locator(parent).locator(child)
        
        if has_text:
            locator = locator.filter(has_text=has_text)
        if has_not_text:
            locator = locator.filter(has_not_text=has_not_text)
        
        return locator
    
    def nth(self, selector: str, index: int) -> Locator:
        """
        第N个元素
        
        Args:
            selector: 选择器
            index: 索引（从0开始）
        """
        return self.page.locator(selector).nth(index)
    
    def first(self, selector: str) -> Locator:
        """第一个匹配元素"""
        return self.page.locator(selector).first
    
    def last(self, selector: str) -> Locator:
        """最后一个匹配元素"""
        return self.page.locator(selector).last
    
    async def smart_find(self, hint: str) -> Optional[Locator]:
        """
        智能查找元素
        尝试多种方式查找元素

        Args:
            hint: 查找提示（文本、ID、class等）
        """
        strategies = [
            # 1. 精确文本匹配
            lambda: self.text(hint, exact=True),
            # 2. 模糊文本匹配
            lambda: self.text(hint),
            # 3. 角色匹配
            lambda: self.role("button", name=hint),
            lambda: self.role("link", name=hint),
            # 4. 占位符
            lambda: self.placeholder(hint),
            # 5. 标签
            lambda: self.label(hint),
            # 6. CSS选择器
            lambda: self.css(hint),
            # 7. XPath
            lambda: self.xpath(f"//*[contains(text(), '{hint}')]"),
        ]

        for strategy in strategies:
            try:
                locator = strategy()
                count = await locator.count()
                if count > 0:
                    logger.debug(f"智能查找成功: hint={hint}")
                    return locator.first
            except:
                continue

        logger.warning(f"智能查找失败: hint={hint}")
        return None
    
    async def all(self, selector: str) -> List[Locator]:
        """获取所有匹配的元素"""
        locator = self.page.locator(selector)
        count = await locator.count()
        return [locator.nth(i) for i in range(count)]

    async def count(self, selector: str) -> int:
        """统计匹配元素数量"""
        return await self.page.locator(selector).count()
