import time
import random
from playwright.sync_api import Page
from playwright.async_api import Page as AsyncPage
from .human_like import HumanLikeTyper
import asyncio
from typing import Union, Optional, Dict, Any


class HumanTypingWrapper:
    """
    人类化输入包装器，提供适度的人类化输入功能
    支持同步和异步页面操作，设计更加简洁高效
    """
    
    def __init__(self, page: Union[Page, AsyncPage], config: Optional[Dict[str, Any]] = None):
        self.page = page
        self.is_async = hasattr(page, 'wait_for_timeout')  # 检测是否为异步页面
        
        # 初始化配置 - 使用更合理的默认值，简化设计
        self.config = self._init_config(config)
        
        # 初始化human_like模块（仅用于同步页面）
        if not self.is_async:
            self.human_typer = HumanLikeTyper(page)
    
    def _init_config(self, config: Optional[Dict[str, Any]]) -> Dict[str, Any]:
        """初始化配置参数
        采用行业标准的人类行为模拟设计：
        - 保持合理的输入速度变化
        - 适度的停顿和错误修正
        - 简化的参数设置，更易维护
        """
        default_config = {
            # 基础输入速度设置（更符合真实人类输入速度范围）
            'min_typing_speed': 2.0,
            'max_typing_speed': 5.0,
            
            # 适度的思考停顿设置
            'pause_probability': 0.1,  # 每10个字符左右停顿一次
            'min_pause_duration': 0.2,
            'max_pause_duration': 1.0,
            
            # 简化的错误修正设置 - 不要过多干扰正常输入
            'correction_probability': 0.05,  # 5%的概率进行错误修正
            
            # 基本的点击前后停顿
            'click_delay_before': (0.2, 0.5),
            'click_delay_after': (0.3, 0.7),
            
            # 输入完成后的停顿
            'finish_pause_probability': 0.6,
            'finish_pause_duration': (0.5, 1.2),
            
            # 分段输入设置 - 更合理的分段长度
            'chunk_input': True,
            'max_chunk_length': 50,  # 更长的段落长度，更符合人类阅读习惯
            'chunk_pause_duration': (0.8, 2.0),
            
            # 最小延迟设置 - 确保不会有机器特征明显的快速输入
            'min_char_delay': 0.08,  # 确保字符间延迟不会过低
        }
        
        if config:
            default_config.update(config)
        
        return default_config
    
    def _calculate_typing_delay(self) -> float:
        """简化的延迟计算方法
        保持合理的随机变化，但避免过度复杂的计算
        """
        # 基础延迟计算
        base_speed = random.uniform(
            self.config['min_typing_speed'], 
            self.config['max_typing_speed']
        )
        
        # 基础延迟（字符间）
        base_delay = 1 / base_speed
        
        # 增加一些随机变化，但保持在合理范围内
        variation = random.uniform(0.8, 1.3)
        final_delay = base_delay * variation
        
        # 确保最小延迟，避免机器特征
        final_delay = max(self.config['min_char_delay'], final_delay)
        
        return final_delay
    
    def _should_pause(self) -> bool:
        """简化的停顿判断逻辑"""
        return random.random() < self.config['pause_probability']
    
    def _should_correct(self) -> bool:
        """判断是否应该进行错误修正"""
        return random.random() < self.config['correction_probability']
    
    def _get_pause_duration(self) -> float:
        """获取随机停顿时长"""
        return random.uniform(
            self.config['min_pause_duration'],
            self.config['max_pause_duration']
        )
    
    def _get_wrong_char(self, correct_char: str) -> str:
        """简化的错误字符生成 - 不需要完整的键盘映射表"""
        # 只保留几个常见的错误类型，减少复杂性
        if correct_char.isalpha():
            # 简单的字母错误（前后移位）
            char_code = ord(correct_char.lower())
            if char_code > ord('a') and char_code < ord('z'):
                # 随机前后移位
                wrong_offset = random.choice([-1, 1])
                wrong_char = chr(char_code + wrong_offset)
                return wrong_char.upper() if correct_char.isupper() else wrong_char
        # 默认返回一个简单的错误字符
        return random.choice('abcdefghijklmnopqrstuvwxyz')
    
    def _record_action(self, action_type: str):
        """空实现的_record_action方法，保持兼容性"""
        pass
    
    async def _sleep(self, duration: float):
        """统一的睡眠方法，兼容同步和异步"""
        if self.is_async:
            await asyncio.sleep(duration)
        else:
            time.sleep(duration)
    
    async def _type_char(self, char: str, delay: float):
        """简化的字符输入方法"""
        if self.is_async:
            await self.page.keyboard.type(char, delay=delay * 1000)
        else:
            self.page.keyboard.type(char, delay=delay * 1000)
        
        # 简单的微小停顿，增加自然感
        await self._sleep(random.uniform(0.02, 0.05))
    
    async def _press_key(self, key: str):
        """按键操作，兼容同步和异步"""
        if self.is_async:
            await self.page.keyboard.press(key)
        else:
            self.page.keyboard.press(key)
        
        # 记录按键动作
        self._record_action(f"key_{key}")
    
    async def _click_element(self, selector: str):
        """点击元素，兼容同步和异步"""
        if self.is_async:
            await self.page.click(selector)
        else:
            self.page.click(selector)
        
        # 记录点击动作
        self._record_action("click")
    
    async def _wait_for_selector(self, selector: str, timeout: int = 30000):
        """等待选择器，兼容同步和异步"""
        if self.is_async:
            await self.page.wait_for_selector(selector, timeout=timeout)
        else:
            self.page.wait_for_selector(selector, timeout=timeout)
    
    async def _perform_random_action(self):
        """简化的随机动作执行 - 不需要过多的动作类型"""
        # 简单的微小停顿就足够模拟人类行为的不确定性
        await self._sleep(random.uniform(0.1, 0.3))
    
    async def type_text_human(self, selector: str, text: str, clear_first: bool = True) -> bool:
        """
        以人类化方式在指定元素中输入文本
        
        Args:
            selector: 元素选择器
            text: 要输入的文本
            clear_first: 是否先清空现有内容
            
        Returns:
            bool: 是否成功输入
        """
        try:
            # 重置历史记录
            self.last_delays = []
            self.action_history = []
            self.input_timestamps = []
            
            # 等待元素并点击
            await self._wait_for_selector(selector)
            
            # 点击前停顿 - 增加随机性和持续时间
            delay_before = random.uniform(*self.config['click_delay_before'])
            await self._sleep(delay_before)
            
            # 模拟光标移动到元素的过程
            await self._sleep(random.uniform(0.1, 0.3))
            
            # 点击元素
            await self._click_element(selector)
            
            # 点击后停顿 - 增加随机性和持续时间
            delay_after = random.uniform(*self.config['click_delay_after'])
            await self._sleep(delay_after)
            
            # 清空现有内容 - 更自然的清空操作，使用更长的延迟
            if clear_first:
                # 增加随机延迟，使清空操作更自然
                await self._sleep(random.uniform(0.2, 0.4))
                await self._press_key("Control+A")
                await self._sleep(random.uniform(0.15, 0.3))
                await self._press_key("Delete")
                await self._sleep(random.uniform(0.3, 0.6))
            
            # 分段输入长文本
            if self.config['chunk_input'] and len(text) > self.config['max_chunk_length']:
                await self._type_text_in_chunks(text)
            else:
                await self._type_text_continuously(text)
            
            # 输入完成后可能停顿 - 更自然的结束停顿
            if random.random() < self.config['finish_pause_probability']:
                pause_duration = random.uniform(*self.config['finish_pause_duration'])
                await self._sleep(pause_duration)
            
            # 输入完成后的最终停顿
            await self._sleep(random.uniform(0.2, 0.5))
            
            return True
            
        except Exception as e:
            print(f"人类化输入失败: {e}")
            return False
    
    async def _type_text_continuously(self, text: str):
        """简化的连续输入方法
        保留必要的人类特征，但避免过度复杂化
        """
        for char in text:
            # 合理的停顿思考
            if self._should_pause():
                pause_duration = self._get_pause_duration()
                await self._sleep(pause_duration)
            
            # 适度的错误修正
            if random.random() < self.config['correction_probability']:
                # 简化的错误修正
                wrong_char = self._get_wrong_char(char)
                await self._type_char(wrong_char, self._calculate_typing_delay())
                await self._sleep(random.uniform(0.1, 0.3))  # 发现错误后的短暂停顿
                await self._press_key("Backspace")  # 删除错误字符
                await self._sleep(random.uniform(0.1, 0.2))  # 删除后的停顿
            
            # 计算延迟并输入字符
            delay = self._calculate_typing_delay()
            await self._type_char(char, delay)
    
    async def _type_text_in_chunks(self, text: str):
        """简化的分段输入方法
        保持基本的段落分割逻辑，但简化实现"""
        chunk_size = self.config['max_chunk_length']
        
        # 简单的分段处理
        for i in range(0, len(text), chunk_size):
            # 获取当前段落，稍微随机化长度
            actual_chunk_size = min(chunk_size, len(text) - i)
            
            # 如果不是最后一段，尽量在空格处分段
            if i + actual_chunk_size < len(text):
                # 寻找段落内最近的空格
                space_pos = text.rfind(' ', i, i + actual_chunk_size + 1)
                if space_pos > i:
                    actual_chunk_size = space_pos - i + 1
            
            # 输入当前段落
            chunk = text[i:i + actual_chunk_size]
            await self._type_text_continuously(chunk)
            
            # 段落间停顿
            if i + actual_chunk_size < len(text):
                pause_duration = random.uniform(*self.config['chunk_pause_duration'])
                await self._sleep(pause_duration)
    
    # 移除了专门的_simul ate_correction和_simul ate_backspace_retype方法
    # 将这些功能合并到_type_text_continuously中，简化实现
    
    async def click_and_type(self, selector: str, text: str, **kwargs) -> bool:
        """
        点击元素并输入文本的便捷方法
        
        Args:
            selector: 元素选择器
            text: 要输入的文本
            **kwargs: 传递给type_text_human的额外参数
            
        Returns:
            bool: 是否成功
        """
        return await self.type_text_human(selector, text, **kwargs)
    
    async def human_click(self, selector: str, wait_after: bool = True) -> bool:
        """
        人类化点击元素
        
        Args:
            selector: 元素选择器
            wait_after: 点击后是否等待
            
        Returns:
            bool: 是否成功点击
        """
        try:
            await self._wait_for_selector(selector)
            
            # 点击前停顿 - 增加随机性
            delay_before = random.uniform(*self.config['click_delay_before'])
            await self._sleep(delay_before)
            
            # 点击
            await self._click_element(selector)
            
            # 点击后停顿
            if wait_after:
                delay_after = random.uniform(*self.config['click_delay_after'])
                await self._sleep(delay_after)
            
            return True
            
        except Exception as e:
            print(f"人类化点击失败: {e}")
            return False
    
    async def human_scroll(self, direction: str = "down", amount: int = 3):
        """
        人类化滚动页面
        
        Args:
            direction: 滚动方向 "up" 或 "down"
            amount: 滚动次数
        """
        key = "PageDown" if direction == "down" else "PageUp"
        
        for i in range(amount):
            await self._press_key(key)
            # 滚动间隔 - 增加随机性和一致性
            pause = random.uniform(0.5, 1.2)  # 增加滚动间隔
            await self._sleep(pause)
            
            # 记录滚动动作
            self._record_action(f"scroll_{direction}")
    
    def update_config(self, new_config: Dict[str, Any]):
        """更新配置"""
        self.config.update(new_config)
    
    def get_config(self) -> Dict[str, Any]:
        """获取当前配置"""
        return self.config.copy()


# 便捷的工厂函数
def create_human_typer(page: Union[Page, AsyncPage], config: Optional[Dict[str, Any]] = None) -> HumanTypingWrapper:
    """
    创建人类化输入包装器的工厂函数
    
    Args:
        page: Playwright页面对象（同步或异步）
        config: 可选的配置字典
        
    Returns:
        HumanTypingWrapper实例
    """
    return HumanTypingWrapper(page, config)
