"""
反检测模块
绕过网站的自动化检测机制
"""
from typing import Optional, Dict, Any
from playwright.async_api import BrowserContext, Page
from loguru import logger
import random


class AntiDetection:
    """
    反检测工具
    绕过网站的自动化检测机制
    """
    
    # 真实用户代理列表
    USER_AGENTS = [
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15",
    ]
    
    # 屏幕分辨率
    SCREEN_SIZES = [
        {"width": 1920, "height": 1080},
        {"width": 1366, "height": 768},
        {"width": 1440, "height": 900},
        {"width": 1536, "height": 864},
        {"width": 2560, "height": 1440},
    ]
    
    # 时区
    TIMEZONES = [
        "Asia/Shanghai",
        "America/New_York",
        "Europe/London",
        "Asia/Tokyo",
    ]
    
    # 语言
    LANGUAGES = [
        "zh-CN",
        "zh-TW",
        "en-US",
        "en-GB",
    ]
    
    # WebGL渲染器
    WEBGL_RENDERERS = [
        "ANGLE (Intel, Intel(R) UHD Graphics 630, OpenGL 4.1)",
        "ANGLE (NVIDIA, NVIDIA GeForce GTX 1060, OpenGL 4.6)",
        "ANGLE (AMD, AMD Radeon RX 580, OpenGL 4.6)",
    ]
    
    @staticmethod
    def get_random_ua() -> str:
        """获取随机用户代理"""
        return random.choice(AntiDetection.USER_AGENTS)
    
    @staticmethod
    def get_random_screen() -> Dict[str, int]:
        """获取随机屏幕尺寸"""
        return random.choice(AntiDetection.SCREEN_SIZES)
    
    @staticmethod
    async def stealth_page(page: Page):
        """
        页面隐身处理
        注入脚本隐藏自动化特征
        """
        # 隐藏 webdriver 属性
        await page.add_init_script("""
            Object.defineProperty(navigator, 'webdriver', {
                get: () => undefined
            });
        """)
        
        # 修改 plugins
        await page.add_init_script("""
            Object.defineProperty(navigator, 'plugins', {
                get: () => [
                    { name: 'Chrome PDF Plugin', filename: 'internal-pdf-viewer' },
                    { name: 'Chrome PDF Viewer', filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai' },
                    { name: 'Native Client', filename: 'internal-nacl-plugin' }
                ]
            });
        """)
        
        # 修改 languages
        await page.add_init_script("""
            Object.defineProperty(navigator, 'languages', {
                get: () => ['zh-CN', 'zh', 'en-US', 'en']
            });
        """)
        
        # 隐藏自动化标志
        await page.add_init_script("""
            // 隐藏 __playwright
            delete window.__playwright;
            
            // 隐藏 __puppeteer
            delete window.__puppeteer;
            
            // 隐藏 __selenium
            delete window.__selenium;
            delete window.__webdriver_evaluate;
            delete window.__webdriver_script_function;
            delete window.__webdriver_script_fn;
            
            // 修改 navigator.platform
            Object.defineProperty(navigator, 'platform', {
                get: () => 'Win32'
            });
            
            // 修改 navigator.hardwareConcurrency
            Object.defineProperty(navigator, 'hardwareConcurrency', {
                get: () => 8
            });
            
            // 修改 navigator.deviceMemory
            Object.defineProperty(navigator, 'deviceMemory', {
                get: () => 8
            });
        """)
        
        # 修改 Chrome 特定属性
        await page.add_init_script("""
            if (window.chrome) {
                window.chrome.runtime = {
                    connect: function() {},
                    sendMessage: function() {}
                };
            }
        """)
        
        # 隐藏权限查询
        await page.add_init_script("""
            const originalQuery = window.navigator.permissions.query;
            window.navigator.permissions.query = (parameters) => (
                parameters.name === 'notifications' ?
                    Promise.resolve({ state: Notification.permission }) :
                    originalQuery(parameters)
            );
        """)
        
        logger.debug("页面隐身处理完成")
    
    @staticmethod
    async def stealth_context(context: BrowserContext):
        """
        浏览器上下文隐身处理
        设置随机的浏览器特征
        """
        # 随机用户代理
        ua = AntiDetection.get_random_ua()
        
        # 随机屏幕尺寸
        screen = AntiDetection.get_random_screen()
        
        # 随机时区
        timezone = random.choice(AntiDetection.TIMEZONES)
        
        # 随机语言
        locale = random.choice(AntiDetection.LANGUAGES)
        
        await context.add_init_script(f"""
            // 设置屏幕尺寸
            Object.defineProperty(screen, 'width', {{ get: () => {screen['width']} }});
            Object.defineProperty(screen, 'height', {{ get: () => {screen['height']} }});
            Object.defineProperty(screen, 'availWidth', {{ get: () => {screen['width']} }});
            Object.defineProperty(screen, 'availHeight', {{ get: () => {screen['height'] - 40} }});
            
            // 设置时区
            Intl.DateTimeFormat.prototype.resolvedOptions = function() {{
                return {{ timeZone: '{timezone}' }};
            }};
        """)
        
        logger.debug(f"上下文隐身处理: ua={ua[:50]}..., screen={screen}, tz={timezone}")
    
    @staticmethod
    def get_context_options(
        user_agent: Optional[str] = None,
        viewport: Optional[Dict[str, int]] = None,
        locale: Optional[str] = None,
        timezone: Optional[str] = None,
    ) -> Dict[str, Any]:
        """
        获取推荐的上上下文选项
        
        Args:
            user_agent: 自定义UA
            viewport: 自定义视口
            locale: 自定义语言
            timezone: 自定义时区
            
        Returns:
            Dict: 上下文选项
        """
        screen = viewport or AntiDetection.get_random_screen()
        
        return {
            "user_agent": user_agent or AntiDetection.get_random_ua(),
            "viewport": screen,
            "locale": locale or random.choice(AntiDetection.LANGUAGES),
            "timezone_id": timezone or random.choice(AntiDetection.TIMEZONES),
            "has_touch": False,
            "is_mobile": False,
            "java_script_enabled": True,
            "ignore_https_errors": True,
        }


class HumanBehavior:
    """
    人类行为模拟
    模拟真实用户的操作行为
    """
    
    @staticmethod
    async def random_delay(min_ms: float = 100, max_ms: float = 500):
        """随机延迟"""
        delay = random.uniform(min_ms, max_ms) / 1000
        await asyncio.sleep(delay)
    
    @staticmethod
    async def human_type(page: Page, selector: str, text: str, delay_range: tuple = (50, 150)):
        """
        人类化输入
        模拟真实打字速度和错误
        
        Args:
            page: 页面对象
            selector: 选择器
            text: 要输入的文本
            delay_range: 延迟范围（毫秒）
        """
        import asyncio
        
        element = page.locator(selector)
        await element.click()
        
        for char in text:
            # 随机延迟
            delay = random.uniform(delay_range[0], delay_range[1]) / 1000
            await asyncio.sleep(delay)
            
            # 偶尔输错（1%概率）
            if random.random() < 0.01 and char.isalpha():
                wrong_char = random.choice('abcdefghijklmnopqrstuvwxyz')
                await page.keyboard.type(wrong_char)
                await asyncio.sleep(0.1)
                await page.keyboard.press('Backspace')
                await asyncio.sleep(0.1)
            
            await page.keyboard.type(char)
        
        logger.debug(f"人类化输入完成: {text[:20]}...")
    
    @staticmethod
    async def human_mouse_move(page: Page, target_x: int, target_y: int):
        """
        人类化鼠标移动
        模拟贝塞尔曲线移动
        
        Args:
            page: 页面对象
            target_x: 目标X
            target_y: 目标Y
        """
        import asyncio
        
        # 简化的贝塞尔曲线模拟
        steps = random.randint(10, 20)
        
        for i in range(steps):
            # 添加随机抖动
            jitter_x = random.randint(-2, 2)
            jitter_y = random.randint(-2, 2)
            
            progress = i / steps
            x = int(target_x * progress) + jitter_x
            y = int(target_y * progress) + jitter_y
            
            await page.mouse.move(x, y)
            await asyncio.sleep(random.uniform(0.01, 0.03))
        
        # 最终移动到目标
        await page.mouse.move(target_x, target_y)
    
    @staticmethod
    async def human_scroll(page: Page, distance: int = 500):
        """
        人类化滚动
        模拟真实滚动速度和停顿
        
        Args:
            page: 页面对象
            distance: 滚动距离
        """
        import asyncio
        
        steps = random.randint(5, 10)
        step_distance = distance // steps
        
        for _ in range(steps):
            await page.mouse.wheel(0, step_distance)
            await asyncio.sleep(random.uniform(0.1, 0.3))
        
        logger.debug(f"人类化滚动完成: distance={distance}")


import asyncio
