"""
元素操作 Mixin
"""
from typing import Optional, TYPE_CHECKING

from loguru import logger
from playwright.async_api import Locator

from ...wait import WaitCondition

if TYPE_CHECKING:
    from ..tab import Tab


class ElementsMixin:
    """元素操作功能"""

    # 这些属性由其他 mixin 或 core 定义
    _tabs: dict[str, "Tab"]
    _current_tab: Optional[str]
    config: "Config"
    highlighter: "ElementHighlighter"
    smart_wait: "SmartWait"

    async def click(
        self,
        selector: str,
        tab_id: Optional[str] = None,
        highlight: bool = True,
        wait_condition: WaitCondition = WaitCondition.CLICKABLE,
        timeout: Optional[float] = None,
        human: Optional[bool] = None,
        force: bool = False,
        dispatch: bool = False,
    ) -> bool:
        """
        点击元素

        Args:
            selector: 元素选择器
            tab_id: 标签页ID
            highlight: 是否高亮
            wait_condition: 等待条件
            timeout: 超时时间
            human: 是否使用人类化点击（None则使用配置）
            force: 是否强制操作隐藏/不可点击元素
            dispatch: 是否使用 dispatch_event('click') 触发点击（适用于隐藏元素）

        Returns:
            bool: 是否成功
        """
        from ...anti_detection import HumanBehavior

        tab = self.get_tab(tab_id)
        locator = tab.page.locator(selector)

        logger.info(f"点击元素: tab={tab.name}, selector={selector}")

        # 智能等待（如果不需要强制操作）
        if not force and not dispatch:
            result = await self.smart_wait.wait_for(locator, wait_condition, timeout)
            if not result.success:
                logger.error(f"点击失败: {result.error}")
                return False

        # 高亮
        if highlight:
            try:
                await self.highlighter.highlight(locator)
            except Exception:
                pass  # 高亮失败不影响操作

        # 决定是否使用人类化点击
        use_human = human if human is not None else self.config.human_behavior_enabled

        if dispatch:
            # 使用 dispatch_event 直接触发点击事件
            await locator.first.dispatch_event('click')
        elif use_human:
            # 获取元素位置并移动鼠标
            box = await locator.first.bounding_box()
            if box:
                target_x = int(box["x"] + box["width"] / 2)
                target_y = int(box["y"] + box["height"] / 2)
                await HumanBehavior.human_mouse_move(tab.page, target_x, target_y)
            await locator.first.click(force=force)
        else:
            await locator.first.click(force=force)

        logger.info(f"点击成功: selector={selector}, human={use_human}, force={force}, dispatch={dispatch}")
        return True

    async def type_text(
        self,
        selector: str,
        text: str,
        tab_id: Optional[str] = None,
        highlight: bool = True,
        clear: bool = False,
        timeout: Optional[float] = None,
        human: Optional[bool] = None,
        force: bool = False,
    ) -> bool:
        """
        输入文本

        Args:
            selector: 元素选择器
            text: 要输入的文本
            tab_id: 标签页ID
            highlight: 是否高亮
            clear: 是否先清空
            timeout: 超时时间
            human: 是否使用人类化输入（None则使用配置）
            force: 是否强制操作隐藏元素

        Returns:
            bool: 是否成功
        """
        from ...anti_detection import HumanBehavior

        tab = self.get_tab(tab_id)
        locator = tab.page.locator(selector)

        logger.info(f"输入文本: tab={tab.name}, selector={selector}, text={text[:50]}...")

        # 等待元素可见（如果不需要强制操作）
        if not force:
            result = await self.smart_wait.wait_for(locator, WaitCondition.VISIBLE, timeout)
            if not result.success:
                logger.error(f"输入失败: {result.error}")
                return False

        # 高亮
        if highlight:
            try:
                await self.highlighter.highlight(locator)
            except Exception:
                pass  # 高亮失败不影响操作

        # 清空
        if clear:
            await locator.clear()

        # 决定是否使用人类化输入
        use_human = human if human is not None else self.config.human_behavior_enabled

        if use_human:
            await HumanBehavior.human_type(
                tab.page,
                selector,
                text,
                delay_range=(self.config.human_type_delay_min, self.config.human_type_delay_max)
            )
        else:
            await locator.first.fill(text, force=force)

        logger.info(f"输入成功: selector={selector}, human={use_human}, force={force}")
        return True

    async def get_text(
        self,
        selector: str,
        tab_id: Optional[str] = None,
        highlight: bool = True,
    ) -> Optional[str]:
        """
        获取元素文本

        Args:
            selector: 元素选择器
            tab_id: 标签页ID
            highlight: 是否高亮

        Returns:
            Optional[str]: 元素文本
        """
        tab = self.get_tab(tab_id)
        locator = tab.page.locator(selector)

        logger.debug(f"获取文本: tab={tab.name}, selector={selector}")

        # 高亮
        if highlight:
            await self.highlighter.highlight(locator)

        text = await locator.text_content()
        logger.debug(f"获取文本成功: text={text[:100] if text else None}...")
        return text

    async def get_value(
        self,
        selector: str,
        tab_id: Optional[str] = None,
        highlight: bool = True,
    ) -> Optional[str]:
        """
        获取输入框值

        Args:
            selector: 元素选择器
            tab_id: 标签页ID
            highlight: 是否高亮

        Returns:
            Optional[str]: 输入值
        """
        tab = self.get_tab(tab_id)
        locator = tab.page.locator(selector)

        if highlight:
            await self.highlighter.highlight(locator)

        value = await locator.input_value()
        logger.debug(f"获取值: selector={selector}, value={value}")
        return value

    async def scroll(
        self,
        selector: Optional[str] = None,
        tab_id: Optional[str] = None,
        direction: str = "down",
        distance: int = 500,
        human: Optional[bool] = None,
    ):
        """
        滚动页面

        Args:
            selector: 元素选择器（可选，滚动到该元素）
            tab_id: 标签页ID
            direction: 滚动方向 (up/down/left/right)
            distance: 滚动距离
            human: 是否使用人类化滚动（None则使用配置）
        """
        from ...anti_detection import HumanBehavior

        tab = self.get_tab(tab_id)

        # 决定是否使用人类化滚动
        use_human = human if human is not None else self.config.human_behavior_enabled

        if selector:
            locator = tab.page.locator(selector)
            await self.highlighter.highlight(locator)
            await locator.scroll_into_view_if_needed()
            logger.info(f"滚动到元素: selector={selector}")
        else:
            if use_human:
                actual_distance = distance if direction == "down" else -distance
                await HumanBehavior.human_scroll(tab.page, abs(actual_distance))
                if direction == "up":
                    await tab.page.evaluate(f"window.scrollTo(0, {distance})")
            else:
                script = f"window.scrollBy(0, {distance if direction == 'down' else -distance})"
                await tab.page.evaluate(script)
            logger.info(f"滚动页面: direction={direction}, distance={distance}, human={use_human}")

    async def screenshot(
        self,
        path: Optional[str] = None,
        tab_id: Optional[str] = None,
        full_page: bool = False,
    ) -> bytes:
        """
        截图

        Args:
            path: 保存路径
            tab_id: 标签页ID
            full_page: 是否全页面截图

        Returns:
            bytes: 截图数据
        """
        tab = self.get_tab(tab_id)
        logger.info(f"截图: tab={tab.name}, full_page={full_page}")

        screenshot = await tab.page.screenshot(path=path, full_page=full_page)
        return screenshot
