# -*- coding: utf-8 -*-
"""
题目生成验证器

负责验证生成题目所需的参数和配置
"""
import logging
from typing import Dict, List, Any, Optional, Tuple

logger = logging.getLogger(__name__)


class GenerationValidator:
    """题目生成验证器"""
    
    @staticmethod
    def validate_ai_config(user_id: int) -> Tuple[bool, Optional[str]]:
        """验证用户 AI 配置
        
        Args:
            user_id: 用户 ID
            
        Returns:
            (是否有效, 错误消息)
        """
        try:
            from app.models.database import AIProviderConfig, SystemAIConfig, AIProviderType
            from app.services.ai.helpers.augment_helper import get_user_augment_token
            from app.models.database.models import SystemConfig
            
            cli_providers = AIProviderType.CLI_PROVIDERS
            ai_config = AIProviderConfig.get_effective_config(user_id)
            
            if not ai_config:
                return False, "请先配置 AI：在「AI配置」页面设置 API Key，或在「个人中心」设置 Augment Session Token"
            
            # 如果是 CLI 模式，只检查 Token 是否存在，不进行实际验证（避免每次生成都发送测试对话）
            if ai_config.provider_type in cli_providers:
                    token_str = get_user_augment_token(user_id)
                    if not token_str:
                        return False, "请先配置 AI：在「AI配置」页面设置 API Key，或在「个人中心」设置 Augment Session Token"
                # 不再进行实际 Token 验证，如果 Token 无效，在生成题目时会自然失败
            
            return True, None
        except Exception as e:
            logger.error(f"验证 AI 配置失败: {str(e)}")
            return False, f"验证 AI 配置失败: {str(e)}"
    
    @staticmethod
    def validate_form_data(
        category_id: str,
        form_data: Dict[str, Any]
    ) -> Tuple[bool, Optional[str], Optional[List[str]]]:
        """验证表单数据
        
        Args:
            category_id: 方向 ID
            form_data: 表单数据
            
        Returns:
            (是否有效, 错误消息, 缺失字段列表)
        """
        from app.models.database.models import CategoryConfig
        
        if not form_data:
            return False, "请先完成题目配置", None
        
        category = CategoryConfig.query.get(category_id)
        if not category:
            return False, f"方向配置不存在: {category_id}", None
        
        # 根据表单配置验证必填字段
        form_fields = category.get_form_fields()
        missing_fields = []
        
        for field in form_fields:
            if field.get('required'):
                field_id = field.get('id')
                field_type = field.get('type')
                field_value = form_data.get(field_id)
                
                # 对于多选字段，检查是否为空列表
                if field_type in ['multi_select', 'multi_select_categorized']:
                    if not field_value or (isinstance(field_value, list) and len(field_value) == 0):
                        missing_fields.append(field.get('label', field_id))
                else:
                    # 对于单选字段，检查是否为空值
                    if not field_value or field_value == '':
                        missing_fields.append(field.get('label', field_id))
        
        if missing_fields:
            return False, f"请先完成题目配置：{', '.join(missing_fields)}", missing_fields
        
        return True, None, None
    
    @staticmethod
    def validate_parameters(
        category_id: str,
        language: Optional[str],
        vulnerabilities: Optional[List[str]],
        scene: Optional[Dict[str, Any]],
        difficulty: str,
        form_data: Optional[Dict[str, Any]] = None
    ) -> Tuple[bool, Optional[str]]:
        """验证生成参数（基于字段配置动态验证）
        
        Args:
            category_id: 方向 ID
            language: 编程语言
            vulnerabilities: 漏洞列表
            scene: 场景
            difficulty: 难度
            form_data: 原始表单数据（可选，用于验证未识别的字段）
            
        Returns:
            (是否有效, 错误消息)
        """
        from app.models.database.models import CategoryConfig
        
        category = CategoryConfig.query.get(category_id)
        if not category:
            logger.warning(f"方向配置不存在: {category_id}")
            return False, "方向配置不存在"
        
        form_fields = category.get_form_fields()
        
        # 动态验证必填字段
        for field in form_fields:
            field_id = field.get('id')
            field_type = field.get('type')
            field_required = field.get('required', False)
            field_hidden = field.get('hidden', False)
            
            # 跳过隐藏字段
            if field_hidden:
                continue
            
            # 只验证必填字段
            if not field_required:
                continue
            
            field_value = None
            
            # 根据字段类型和属性识别字段（按优先级顺序检查）
            if field_type == 'select':
                # 优先级1: 检查是否是语言字段（通过 options_source 识别最准确）
                if field.get('options_source') == 'languages':
                    field_value = language
                    logger.debug(f"字段 {field_id} 识别为语言字段，值: {field_value}")
                # 优先级2: 检查是否是场景字段
                elif field.get('options_source') == 'scenes' or 'scene' in field_id.lower():
                    field_value = scene
                    logger.debug(f"字段 {field_id} 识别为场景字段，值: {field_value}")
                # 优先级3: 检查是否是难度字段（通过选项值识别）
                else:
                    options = field.get('options', [])
                    difficulty_values = ['入门', '简单', '中等', '困难', 'beginner', 'easy', 'medium', 'hard']
                    if any(opt.get('value') in difficulty_values for opt in options):
                        field_value = difficulty
                        logger.debug(f"字段 {field_id} 识别为难度字段，值: {field_value}")
            
            elif field_type in ['multi_select', 'multi_select_categorized']:
                field_value = vulnerabilities
                logger.debug(f"字段 {field_id} 识别为知识点字段，值: {field_value}")
            
            # 如果仍然无法识别，尝试从 form_data 中获取值
            if field_value is None and form_data:
                field_value = form_data.get(field_id)
                logger.debug(f"从 form_data 获取字段值: {field_id} = {field_value}")
            
            # 验证必填字段
            if field_required:
                if field_value is None:
                    logger.warning(f"必填字段 {field_id} ({field.get('label', field_id)}) 值为 None, language={language}, vulnerabilities={vulnerabilities}, scene={scene}, difficulty={difficulty}")
                    return False, f"请先选择 {field.get('label', field_id)}"
                elif isinstance(field_value, str) and not field_value.strip():
                    logger.warning(f"必填字段 {field_id} ({field.get('label', field_id)}) 值为空字符串")
                    return False, f"请先选择 {field.get('label', field_id)}"
                elif isinstance(field_value, list) and len(field_value) == 0:
                    logger.warning(f"必填字段 {field_id} ({field.get('label', field_id)}) 值为空列表")
                    return False, f"请先选择 {field.get('label', field_id)}"
                elif isinstance(field_value, dict) and not field_value.get('no_scene'):
                    # 场景字段：如果是字典但没有 no_scene 标记，需要检查是否有有效值
                    if not field_value.get('name') and not field_value.get('id'):
                        logger.warning(f"必填字段 {field_id} ({field.get('label', field_id)}) 场景字典无效")
                        return False, f"请先选择 {field.get('label', field_id)}"
        
        # 验证难度（所有方向都需要）
        if not difficulty or (isinstance(difficulty, str) and not difficulty.strip()):
            logger.warning(f"难度验证失败: difficulty={difficulty}, type={type(difficulty)}")
            return False, "请先选择难度级别"
        
        return True, None

