"""
Schema 转换器
将 sqlParams 数组格式转换为 MCP 工具需要的 JSON Schema 格式

支持的类型:
- string: 文本输入
- paragraph: 段落/多行文本
- select: 下拉选项
- number: 数字输入
- file: 单文件上传
- fileList: 多文件上传
"""
import json
from typing import Any


def sanitize_json_schema(schema: dict) -> dict:
    """
    清理 JSON Schema，确保 enum 字段只包含字符串值
    
    Args:
        schema: 原始 JSON Schema
    
    Returns:
        dict: 清理后的 JSON Schema
    """
    if not isinstance(schema, dict):
        return schema
    
    # 递归处理 properties
    if "properties" in schema and isinstance(schema["properties"], dict):
        for prop_name, prop_schema in schema["properties"].items():
            if isinstance(prop_schema, dict) and "enum" in prop_schema:
                enum_values = prop_schema["enum"]
                if isinstance(enum_values, list) and len(enum_values) > 0:
                    # 检查是否是对象数组
                    if isinstance(enum_values[0], dict):
                        # 提取 value 字段
                        cleaned_enum = [
                            item.get("value", item.get("label", ""))
                            for item in enum_values
                            if isinstance(item, dict)
                        ]
                        # 过滤空值
                        prop_schema["enum"] = [v for v in cleaned_enum if v]
                        # 保留原始数据
                        prop_schema["x-options"] = enum_values
    
    return schema


def convert_param_to_schema_property(param: dict) -> tuple[str, dict, bool]:
    """
    将单个参数转换为 JSON Schema property
    
    Args:
        param: 参数配置，格式如:
            {
                "type": "string",
                "name": "company_names",
                "displayName": "公司名称",
                "maxLength": 200,
                "defaultValue": "",
                "required": true,
                "options": ["选项1", "选项2"],  # 仅 select 类型
                "fileConfig": {  # 仅 file/fileList 类型
                    "uploadMode": "both",
                    "typeCategories": ["image"],
                    "customAccept": "",
                    "accept": ".jpg,.jpeg,.png"
                }
            }
    
    Returns:
        tuple: (property_name, property_schema, is_required)
    """
    param_type = param.get("type", "string")
    param_name = param.get("name", "")
    display_name = param.get("displayName", param_name)
    default_value = param.get("defaultValue", "")
    max_length = param.get("maxLength")
    is_required = param.get("required", False)
    options = param.get("options", [])
    file_config = param.get("fileConfig", {})
    
    property_schema = {
        "description": display_name
    }
    
    if param_type == "string":
        property_schema["type"] = "string"
        if max_length:
            property_schema["maxLength"] = max_length
            
    elif param_type == "paragraph":
        property_schema["type"] = "string"
        property_schema["format"] = "paragraph"
        if max_length:
            property_schema["maxLength"] = max_length
            
    elif param_type == "select":
        property_schema["type"] = "string"
        if options:
            # 处理 options 可能是对象数组 [{label, value}] 或字符串数组的情况
            if isinstance(options, list) and len(options) > 0:
                if isinstance(options[0], dict):
                    # 对象数组，提取 value 字段作为 enum，过滤空值
                    enum_values = [
                        opt.get("value", opt.get("label", "")) 
                        for opt in options 
                        if isinstance(opt, dict)
                    ]
                    # 过滤掉空字符串
                    property_schema["enum"] = [v for v in enum_values if v]
                    # 保留原始 options 供前端使用（如果前端支持）
                    property_schema["x-options"] = options
                else:
                    # 字符串数组，直接使用，过滤空值
                    property_schema["enum"] = [v for v in options if v]
            
    elif param_type == "number":
        property_schema["type"] = "number"
        
    elif param_type == "file":
        # 单文件上传
        property_schema["type"] = "string"
        property_schema["format"] = "url"
        property_schema["x-file-type"] = "single"
        
        # 添加文件配置信息
        if file_config:
            if file_config.get("accept"):
                property_schema["x-accept"] = file_config["accept"]
            if file_config.get("typeCategories"):
                property_schema["x-type-categories"] = file_config["typeCategories"]
            if file_config.get("uploadMode"):
                property_schema["x-upload-mode"] = file_config["uploadMode"]
            # 保留完整配置
            property_schema["x-file-config"] = file_config
            
    elif param_type == "fileList":
        # 多文件上传
        property_schema["type"] = "array"
        property_schema["items"] = {
            "type": "string",
            "format": "url"
        }
        property_schema["x-file-type"] = "multiple"
        
        # 添加文件配置信息
        if file_config:
            if file_config.get("accept"):
                property_schema["x-accept"] = file_config["accept"]
            if file_config.get("typeCategories"):
                property_schema["x-type-categories"] = file_config["typeCategories"]
            if file_config.get("uploadMode"):
                property_schema["x-upload-mode"] = file_config["uploadMode"]
            # 保留完整配置
            property_schema["x-file-config"] = file_config
        
    else:
        # 默认当作 string 处理
        property_schema["type"] = "string"
    
    # 添加默认值（文件类型不需要默认值）
    if default_value not in (None, "") and param_type not in ("file", "fileList"):
        if param_type == "number":
            try:
                property_schema["default"] = int(default_value) if str(default_value).isdigit() else float(default_value)
            except (ValueError, TypeError):
                property_schema["default"] = default_value
        else:
            property_schema["default"] = default_value
    
    return param_name, property_schema, is_required


def convert_sql_params_to_input_schema(sql_params: str | list) -> dict:
    """
    将 sqlParams 转换为 MCP 工具的 inputSchema
    
    Args:
        sql_params: sqlParams 字段值，可以是 JSON 字符串或已解析的列表
            格式: [{"type": "string", "name": "xxx", ...}, ...]
    
    Returns:
        dict: MCP 工具的 inputSchema，格式如:
            {
                "type": "object",
                "properties": {...},
                "required": [...]
            }
    """
    # 解析 JSON 字符串
    if isinstance(sql_params, str):
        try:
            params_list = json.loads(sql_params)
        except json.JSONDecodeError:
            return {"type": "object", "properties": {}, "required": []}
    else:
        params_list = sql_params
    
    if not isinstance(params_list, list):
        return {"type": "object", "properties": {}, "required": []}
    
    input_schema = {
        "type": "object",
        "properties": {},
        "required": []
    }
    
    for param in params_list:
        if not isinstance(param, dict):
            continue
            
        name, schema, is_required = convert_param_to_schema_property(param)
        
        if name:
            input_schema["properties"][name] = schema
            if is_required:
                input_schema["required"].append(name)
    
    return input_schema


def convert_business_query_to_tool(query: dict) -> dict:
    """
    将单个 businessQuery 转换为 MCP Tool 配置
    
    Args:
        query: businessQuery 对象
    
    Returns:
        dict: MCP Tool 配置
            {
                "name": "工具名称",
                "description": "工具描述",
                "inputSchema": {...}
            }
    """
    name = query.get("name", "")
    description = query.get("description") or query.get("toolPrompt") or query.get("uniqueName", "")
    sql_params = query.get("sqlParams", "[]")
    
    input_schema = convert_sql_params_to_input_schema(sql_params)
    
    return {
        "name": name,
        "description": description,
        "inputSchema": input_schema,
        # 保留原始数据供后续使用
        "_raw": {
            "id": query.get("id"),
            "uniqueName": query.get("uniqueName"),
            "sqlTemplate": query.get("sqlTemplate"),
            "datasourceId": query.get("datasourceId"),
            "toolType": query.get("toolType"),
        }
    }


def convert_all_queries_to_tools(queries: list[dict]) -> list[dict]:
    """
    将所有 businessQueries 转换为 MCP Tools 列表
    
    Args:
        queries: businessQueries 列表
    
    Returns:
        list: MCP Tools 配置列表
    """
    tools = []
    for query in queries:
        tool = convert_business_query_to_tool(query)
        if tool["name"]:
            tools.append(tool)
    return tools


# 测试用
if __name__ == "__main__":
    # 测试单个参数转换
    test_param = {
        "type": "select",
        "name": "subject_name",
        "displayName": "科目名称",
        "maxLength": 100,
        "defaultValue": "",
        "required": True,
        "options": ["管理费用", "销售费用", "财务费用"]
    }
    
    name, schema, required = convert_param_to_schema_property(test_param)
    print(f"参数名: {name}")
    print(f"Schema: {json.dumps(schema, ensure_ascii=False, indent=2)}")
    print(f"必填: {required}")
    print()
    
    # 测试完整 sqlParams 转换
    test_sql_params = '[{"type":"paragraph","name":"digest","displayName":"摘要关键字","maxLength":500,"defaultValue":"","required":true},{"type":"string","name":"company_names","displayName":"公司名称","maxLength":200,"defaultValue":"","required":false},{"type":"number","name":"year","displayName":"会计年度","maxLength":4,"defaultValue":"2025","required":true}]'
    
    input_schema = convert_sql_params_to_input_schema(test_sql_params)
    print("InputSchema:")
    print(json.dumps(input_schema, ensure_ascii=False, indent=2))
