"""
数据验证增强模块 - 解决专家测试发现的数据验证问题
"""
from typing import Dict, List, Optional, Any, Tuple
import re

class InputValidator:
    """输入验证器 - 增强数据验证"""
    
    def __init__(self):
        # 验证规则
        self.validation_rules = {
            "relation": {
                "required": False,  # 不强制要求，可能在其他地方验证
                "allowed_values": ["妈妈", "爸爸", "女友", "男友", "朋友", "同事", "领导", "客户", "老师", "长辈", "孩子"],
                "min_length": 1,
                "max_length": 10
            },
            "occasion": {
                "required": False,  # 不强制要求
                "allowed_values": ["生日", "情人节", "纪念日", "母亲节", "父亲节", "节日", "乔迁", "结婚", "道歉", "感谢"],
                "min_length": 1,
                "max_length": 10
            },
            "budget_min": {
                "required": False,
                "type": int,
                "min_value": 1,
                "max_value": 1000000
            },
            "budget_max": {
                "required": False,
                "type": int,
                "min_value": 1,
                "max_value": 1000000
            },
            "text": {
                "required": False,  # 不是所有API都需要文本
                "min_length": 1,
                "max_length": 500,
                "regex": r'^[\w\W\u4e00-\u9fa5\s\.\,\!\?，。！？、；：\"\"\'\'（）()【】\[\]《》<>]+$'
            }
        }
        
        # 安全规则
        self.security_rules = {
            "sql_injection_patterns": [
                r'\s*union\s+select\s*',
                r'\s*or\s+1\s*=\s*1\s*',
                r'\s*;\s*--',
                r'\s*drop\s+table\s*',
                r'\s*delete\s+from\s*'
            ],
            "xss_patterns": [
                r'<script[^>]*>',
                r'javascript:',
                r'on\w+\s*=',
                r'data:text/html'
            ],
            "path_traversal_patterns": [
                r'\.\./',
                r'\.\.\\',
                r'%2e%2e%2f',
                r'%252e%252e%252f'
            ]
        }
    
    def validate_input(self, input_data: Dict) -> Tuple[bool, List[str]]:
        """验证输入数据"""
        errors = []
        
        # 基础验证
        for field, rules in self.validation_rules.items():
            if rules.get("required") and field not in input_data:
                errors.append(f"缺少必填字段: {field}")
                continue
            
            if field in input_data:
                value = input_data[field]
                
                # 类型验证
                if "type" in rules:
                    expected_type = rules["type"]
                    if expected_type == int and not isinstance(value, int):
                        try:
                            input_data[field] = int(value)
                        except (ValueError, TypeError):
                            errors.append(f"字段 {field} 应为整数类型")
                
                # 值范围验证
                if "allowed_values" in rules and value not in rules["allowed_values"]:
                    errors.append(f"字段 {field} 的值 '{value}' 不在允许范围内")
                
                # 长度验证
                if isinstance(value, str):
                    if "min_length" in rules and len(value) < rules["min_length"]:
                        errors.append(f"字段 {field} 长度不能小于 {rules['min_length']}")
                    if "max_length" in rules and len(value) > rules["max_length"]:
                        errors.append(f"字段 {field} 长度不能大于 {rules['max_length']}")
                
                # 数值范围验证
                if isinstance(value, (int, float)):
                    if "min_value" in rules and value < rules["min_value"]:
                        errors.append(f"字段 {field} 的值不能小于 {rules['min_value']}")
                    if "max_value" in rules and value > rules["max_value"]:
                        errors.append(f"字段 {field} 的值不能大于 {rules['max_value']}")
        
        # 预算验证
        if "budget_min" in input_data and "budget_max" in input_data:
            if input_data["budget_min"] > input_data["budget_max"]:
                errors.append("最低预算不能大于最高预算")
        
        # 安全验证
        security_errors = self._security_validation(input_data)
        errors.extend(security_errors)
        
        return len(errors) == 0, errors
    
    def _security_validation(self, input_data: Dict) -> List[str]:
        """安全验证"""
        errors = []
        
        for key, value in input_data.items():
            if isinstance(value, str):
                value_str = str(value).lower()
                
                # SQL注入检测
                for pattern in self.security_rules["sql_injection_patterns"]:
                    if re.search(pattern, value_str):
                        errors.append(f"字段 {key} 包含可疑SQL注入内容")
                        break
                
                # XSS检测
                for pattern in self.security_rules["xss_patterns"]:
                    if re.search(pattern, value_str):
                        errors.append(f"字段 {key} 包含可疑XSS内容")
                        break
                
                # 路径遍历检测
                for pattern in self.security_rules["path_traversal_patterns"]:
                    if re.search(pattern, value_str):
                        errors.append(f"字段 {key} 包含可疑路径遍历内容")
                        break
        
        return errors
    
    def sanitize_input(self, input_data: Dict) -> Dict:
        """清理输入数据"""
        sanitized = {}
        
        for key, value in input_data.items():
            if isinstance(value, str):
                # 移除多余空格
                value = value.strip()
                # 移除HTML标签
                value = re.sub(r'<[^>]*>', '', value)
                # 限制长度
                if key in self.validation_rules and "max_length" in self.validation_rules[key]:
                    max_len = self.validation_rules[key]["max_length"]
                    if len(value) > max_len:
                        value = value[:max_len]
                # 转义特殊字符
                value = value.replace("'", "''").replace('"', '""')
            
            elif isinstance(value, (int, float)):
                # 数值范围限制
                if key in self.validation_rules:
                    if "min_value" in self.validation_rules[key]:
                        value = max(value, self.validation_rules[key]["min_value"])
                    if "max_value" in self.validation_rules[key]:
                        value = min(value, self.validation_rules[key]["max_value"])
            
            sanitized[key] = value
        
        return sanitized
    
    def validate_natural_language(self, text: str) -> Tuple[bool, List[str]]:
        """验证自然语言输入"""
        errors = []
        
        if not text or len(text.strip()) == 0:
            errors.append("输入不能为空")
            return False, errors
        
        # 长度检查
        if len(text) > 500:
            errors.append("输入文本过长（最多500字符）")
        
        # 内容检查
        if len(text) < 5:
            errors.append("输入文本过短（至少5字符）")
        
        # 关键词检查（确保有足够信息）
        required_keywords = ["送", "礼物", "选", "推荐", "买"]
        relation_keywords = ["妈妈", "爸爸", "女友", "朋友", "同事", "领导"]
        occasion_keywords = ["生日", "情人节", "节日", "纪念日"]
        
        has_required = any(keyword in text for keyword in required_keywords)
        has_relation = any(keyword in text for keyword in relation_keywords)
        has_occasion = any(keyword in text for keyword in occasion_keywords)
        
        if not has_required and not has_relation and not has_occasion:
            # 可能用户已经进入对话模式，这个检查可以放松
            pass
        
        # 安全验证
        text_lower = text.lower()
        for pattern in self.security_rules["sql_injection_patterns"]:
            if re.search(pattern, text_lower):
                errors.append("输入包含可疑内容（SQL注入）")
                break
        
        for pattern in self.security_rules["xss_patterns"]:
            if re.search(pattern, text_lower):
                errors.append("输入包含可疑内容（XSS攻击）")
                break
        
        return len(errors) == 0, errors

# 全局验证器实例
validator = InputValidator()

# 便捷函数
def validate_gift_request(relation: Optional[str], occasion: Optional[str], 
                         budget_min: Optional[int], budget_max: Optional[int]) -> Tuple[bool, List[str]]:
    """验证礼物请求参数"""
    input_data = {}
    if relation:
        input_data["relation"] = relation
    if occasion:
        input_data["occasion"] = occasion
    if budget_min is not None:
        input_data["budget_min"] = budget_min
    if budget_max is not None:
        input_data["budget_max"] = budget_max
    
    return validator.validate_input(input_data)

def sanitize_user_input(input_text: str) -> str:
    """清理用户输入文本"""
    sanitized = validator.sanitize_input({"text": input_text})
    return sanitized.get("text", "")

# 测试
if __name__ == "__main__":
    print("=== 数据验证模块测试 ===")
    
    # 测试1：正常输入
    test1 = {"relation": "妈妈", "occasion": "生日", "budget_min": 200, "budget_max": 1000}
    valid1, errors1 = validator.validate_input(test1)
    print(f"测试1 - 正常输入: {'✅' if valid1 else '❌'}")
    if errors1:
        print(f"  错误: {errors1}")
    
    # 测试2：异常输入
    test2 = {"relation": "黑客", "occasion": "测试", "budget_min": -100}
    valid2, errors2 = validator.validate_input(test2)
    print(f"测试2 - 异常输入: {'✅' if valid2 else '❌'}")
    if errors2:
        print(f"  错误: {errors2}")
    
    # 测试3：安全输入验证
    test3_text = "送妈妈生日礼物<script>alert('xss')</script>"
    valid3, errors3 = validator.validate_natural_language(test3_text)
    print(f"测试3 - 安全验证: {'✅' if valid3 else '❌'}")
    if errors3:
        print(f"  错误: {errors3}")
    
    # 测试4：清理输入
    dirty_input = "送妈妈  <b>生日</b>  礼物' OR '1'='1"
    clean_input = sanitize_user_input(dirty_input)
    print(f"测试4 - 输入清理:")
    print(f"  原始: {dirty_input}")
    print(f"  清理后: {clean_input}")
    
    print("\n✅ 验证模块测试完成")