"""
Snowflake Cortex AI 节点

包含两个节点：
1. SnowflakeCortexLLMNode - Cortex LLM Functions (COMPLETE, SUMMARIZE, TRANSLATE 等)
2. SnowflakeCortexAnalystNode - Cortex Analyst (自然语言查询数据)
"""
import json
import logging
import time
from typing import Any, Dict, List, Optional

from ..base import BaseNode, NodeContext, NodeResult
from ..registry import NodeRegistry

logger = logging.getLogger(__name__)


class SnowflakeConnectionMixin:
    """Snowflake 连接混入类"""
    
    # 支持的认证方式
    AUTH_TYPES = [
        ('password', '用户名/密码'),
        ('key_pair', '密钥对 (Key Pair)'),
        ('externalbrowser', '外部浏览器 SSO'),
    ]
    
    def _get_connection(self, config: Dict, context: NodeContext):
        """
        获取 Snowflake 连接
        
        支持多种认证方式：
        - password: 用户名密码认证
        - key_pair: RSA 密钥对认证（推荐生产环境使用）
        - externalbrowser: 外部浏览器 SSO 认证
        
        Args:
            config: 节点配置
            context: 执行上下文
            
        Returns:
            snowflake.connector.connection
        """
        try:
            import snowflake.connector
        except ImportError:
            raise ImportError('请安装 snowflake-connector-python: pip install snowflake-connector-python')
        
        # 从配置获取连接信息
        connection_config = config.get('connection', {})
        
        # 认证方式，默认为密码认证
        auth_type = connection_config.get('auth_type', 'password')
        
        # 支持变量引用 - 基础参数
        account = context.resolve_template(connection_config.get('account', ''))
        user = context.resolve_template(connection_config.get('user', ''))
        warehouse = context.resolve_template(connection_config.get('warehouse', ''))
        database = context.resolve_template(connection_config.get('database', ''))
        schema = context.resolve_template(connection_config.get('schema', 'PUBLIC'))
        role = context.resolve_template(connection_config.get('role', ''))
        
        # 验证必填参数
        if not account:
            raise ValueError('Snowflake 连接缺少 account 配置')
        if not user:
            raise ValueError('Snowflake 连接缺少 user 配置')
        if not warehouse:
            raise ValueError('Snowflake 连接缺少 warehouse 配置')
        if not database:
            raise ValueError('Snowflake 连接缺少 database 配置')
        
        conn_params = {
            'account': account,
            'user': user,
            'warehouse': warehouse,
            'database': database,
            'schema': schema,
        }
        
        if role:
            conn_params['role'] = role
        
        # 根据认证方式设置认证参数
        if auth_type == 'password':
            password = context.resolve_template(connection_config.get('password', ''))
            if not password:
                raise ValueError('密码认证方式需要配置 password')
            conn_params['password'] = password
            
        elif auth_type == 'key_pair':
            # 密钥对认证
            private_key = context.resolve_template(connection_config.get('private_key', ''))
            private_key_path = context.resolve_template(connection_config.get('private_key_path', ''))
            private_key_passphrase = context.resolve_template(connection_config.get('private_key_passphrase', ''))
            
            if private_key:
                # 直接使用私钥内容
                conn_params['private_key'] = self._load_private_key_from_string(
                    private_key, private_key_passphrase
                )
            elif private_key_path:
                # 从文件路径加载私钥
                conn_params['private_key'] = self._load_private_key_from_file(
                    private_key_path, private_key_passphrase
                )
            else:
                raise ValueError('密钥对认证需要配置 private_key 或 private_key_path')
                
        elif auth_type == 'externalbrowser':
            # 外部浏览器 SSO 认证
            conn_params['authenticator'] = 'externalbrowser'
            
        else:
            raise ValueError(f'不支持的认证方式: {auth_type}')
        
        logger.info(f'Snowflake 连接: account={account}, user={user}, auth_type={auth_type}')
        
        return snowflake.connector.connect(**conn_params)
    
    def _load_private_key_from_string(self, private_key_str: str, passphrase: str = '') -> bytes:
        """从字符串加载 RSA 私钥"""
        from cryptography.hazmat.backends import default_backend
        from cryptography.hazmat.primitives import serialization
        
        # 处理可能的转义换行符
        private_key_str = private_key_str.replace('\\n', '\n')
        
        p_key = serialization.load_pem_private_key(
            private_key_str.encode('utf-8'),
            password=passphrase.encode('utf-8') if passphrase else None,
            backend=default_backend()
        )
        
        return p_key.private_bytes(
            encoding=serialization.Encoding.DER,
            format=serialization.PrivateFormat.PKCS8,
            encryption_algorithm=serialization.NoEncryption()
        )
    
    def _load_private_key_from_file(self, file_path: str, passphrase: str = '') -> bytes:
        """从文件加载 RSA 私钥"""
        from cryptography.hazmat.backends import default_backend
        from cryptography.hazmat.primitives import serialization
        
        with open(file_path, 'rb') as key_file:
            p_key = serialization.load_pem_private_key(
                key_file.read(),
                password=passphrase.encode('utf-8') if passphrase else None,
                backend=default_backend()
            )
        
        return p_key.private_bytes(
            encoding=serialization.Encoding.DER,
            format=serialization.PrivateFormat.PKCS8,
            encryption_algorithm=serialization.NoEncryption()
        )


@NodeRegistry.register
class SnowflakeCortexLLMNode(BaseNode, SnowflakeConnectionMixin):
    """
    Snowflake Cortex LLM Functions 节点
    
    支持的功能：
    - COMPLETE: LLM 文本生成
    - SUMMARIZE: 文本摘要
    - TRANSLATE: 翻译
    - SENTIMENT: 情感分析
    - EXTRACT_ANSWER: 问答提取
    """
    
    node_type = 'snowflake_cortex_llm'
    node_name = 'Snowflake Cortex LLM'
    node_category = 'ai'
    node_icon = 'snowflake'
    node_description = 'Snowflake Cortex AI 函数（LLM 生成、摘要、翻译、情感分析等）'
    
    # 支持的 Cortex 模型
    CORTEX_MODELS = [
        'mistral-large',
        'mistral-large2',
        'mistral-7b',
        'mixtral-8x7b',
        'llama3-8b',
        'llama3-70b',
        'llama3.1-8b',
        'llama3.1-70b',
        'llama3.1-405b',
        'llama3.2-1b',
        'llama3.2-3b',
        'snowflake-arctic',
        'reka-core',
        'reka-flash',
        'jamba-instruct',
        'jamba-1.5-mini',
        'jamba-1.5-large',
        'gemma-7b',
    ]
    
    # 支持的功能类型
    FUNCTION_TYPES = [
        ('complete', 'LLM 生成 (COMPLETE)'),
        ('summarize', '文本摘要 (SUMMARIZE)'),
        ('translate', '翻译 (TRANSLATE)'),
        ('sentiment', '情感分析 (SENTIMENT)'),
        ('extract_answer', '问答提取 (EXTRACT_ANSWER)'),
    ]
    
    inputs = [
        {
            'name': 'text',
            'type': 'string',
            'description': '输入文本',
        },
    ]
    
    outputs = [
        {
            'name': 'result',
            'type': 'string',
            'description': 'Cortex 输出结果',
        },
    ]
    
    def execute(self, context: NodeContext) -> NodeResult:
        """执行 Cortex LLM 函数"""
        start_time = time.time()
        
        try:
            function_type = self.config.get('function', 'complete')
            
            # 根据功能类型执行
            if function_type == 'complete':
                result = self._execute_complete(context)
            elif function_type == 'summarize':
                result = self._execute_summarize(context)
            elif function_type == 'translate':
                result = self._execute_translate(context)
            elif function_type == 'sentiment':
                result = self._execute_sentiment(context)
            elif function_type == 'extract_answer':
                result = self._execute_extract_answer(context)
            else:
                return NodeResult(
                    success=False,
                    error=f'不支持的功能类型: {function_type}',
                )
            
            elapsed_time = int((time.time() - start_time) * 1000)
            output_var = self.config.get('output_variable', 'cortex_result')
            
            return NodeResult(
                success=True,
                output=result,
                output_variables={output_var: result},
                elapsed_time=elapsed_time,
                metadata={'function': function_type},
            )
            
        except Exception as e:
            logger.exception(f'Snowflake Cortex LLM 节点执行失败: {e}')
            elapsed_time = int((time.time() - start_time) * 1000)
            return NodeResult(
                success=False,
                error=str(e),
                elapsed_time=elapsed_time,
            )
    
    def _execute_complete(self, context: NodeContext) -> str:
        """
        执行 COMPLETE 函数 - 使用 REST API 方式
        
        API 端点: /api/v2/cortex/inference:complete
        """
        import requests
        
        config = self.config.get('complete', {})
        model = config.get('model', 'mistral-large')
        prompt = context.resolve_template(config.get('prompt', ''))
        system_prompt = context.resolve_template(config.get('system_prompt', ''))
        temperature = config.get('temperature', 0.7)
        max_tokens = config.get('max_tokens', 1024)
        
        if not prompt:
            raise ValueError('COMPLETE 功能需要配置 prompt')
        
        connection_config = self.config.get('connection', {})
        account = context.resolve_template(connection_config.get('account', ''))
        
        # 获取连接以获取 session token
        conn = self._get_connection(self.config, context)
        
        try:
            # 从连接中获取 REST session token
            rest_token = conn.rest.token
            
            # 构建 API URL
            if '.snowflakecomputing.com' in account:
                host = account
            else:
                host = conn.host if hasattr(conn, 'host') else f'{account}.snowflakecomputing.com'
            
            api_url = f"https://{host}/api/v2/cortex/inference:complete"
            
            # 构建请求头
            headers = {
                'Content-Type': 'application/json',
                'Accept': 'application/json',
                'Authorization': f'Snowflake Token="{rest_token}"',
            }
            
            # 构建消息
            messages = []
            if system_prompt:
                messages.append({'role': 'system', 'content': system_prompt})
            messages.append({'role': 'user', 'content': prompt})
            
            # 构建请求体
            payload = {
                'model': model,
                'messages': messages,
                'temperature': temperature,
                'max_tokens': max_tokens,
            }
            
            logger.info(f'调用 Cortex LLM API: {api_url}')
            logger.info(f'Model: {model}, Temperature: {temperature}, Max Tokens: {max_tokens}')
            
            response = requests.post(
                api_url,
                json=payload,
                headers=headers,
                timeout=120,
            )
            
            logger.info(f'Cortex LLM 响应状态: {response.status_code}')
            
            if response.status_code != 200:
                error_text = response.text
                logger.error(f'Cortex LLM API 错误: {error_text}')
                raise ValueError(f'Cortex LLM API 调用失败: {response.status_code} - {error_text}')
            
            # 解析响应 - REST API 返回 SSE 格式
            result_content = ''
            response_text = response.text
            
            # 解析 SSE 格式的响应
            for line in response_text.split('\n'):
                if line.startswith('data:'):
                    data_str = line[5:].strip()
                    if data_str:
                        try:
                            data = json.loads(data_str)
                            if 'choices' in data and len(data['choices']) > 0:
                                choice = data['choices'][0]
                                if 'delta' in choice and 'content' in choice['delta']:
                                    result_content += choice['delta']['content']
                        except json.JSONDecodeError:
                            pass
            
            return result_content if result_content else response_text
            
        finally:
            conn.close()
    
    def _execute_summarize(self, context: NodeContext) -> str:
        """执行 SUMMARIZE 函数"""
        config = self.config.get('summarize', {})
        text = context.resolve_template(config.get('text', ''))
        
        if not text:
            raise ValueError('SUMMARIZE 功能需要配置 text')
        
        conn = self._get_connection(self.config, context)
        try:
            cursor = conn.cursor()
            sql = "SELECT SNOWFLAKE.CORTEX.SUMMARIZE(%s)"
            cursor.execute(sql, (text,))
            row = cursor.fetchone()
            return row[0] if row else ''
        finally:
            conn.close()
    
    def _execute_translate(self, context: NodeContext) -> str:
        """执行 TRANSLATE 函数"""
        config = self.config.get('translate', {})
        text = context.resolve_template(config.get('text', ''))
        source_language = config.get('source_language', 'en')
        target_language = config.get('target_language', 'zh')
        
        if not text:
            raise ValueError('TRANSLATE 功能需要配置 text')
        
        conn = self._get_connection(self.config, context)
        try:
            cursor = conn.cursor()
            sql = "SELECT SNOWFLAKE.CORTEX.TRANSLATE(%s, %s, %s)"
            cursor.execute(sql, (text, source_language, target_language))
            row = cursor.fetchone()
            return row[0] if row else ''
        finally:
            conn.close()
    
    def _execute_sentiment(self, context: NodeContext) -> str:
        """执行 SENTIMENT 函数"""
        config = self.config.get('sentiment', {})
        text = context.resolve_template(config.get('text', ''))
        
        if not text:
            raise ValueError('SENTIMENT 功能需要配置 text')
        
        conn = self._get_connection(self.config, context)
        try:
            cursor = conn.cursor()
            sql = "SELECT SNOWFLAKE.CORTEX.SENTIMENT(%s)"
            cursor.execute(sql, (text,))
            row = cursor.fetchone()
            # SENTIMENT 返回 -1 到 1 的数值
            result = row[0] if row else 0
            return str(result)
        finally:
            conn.close()
    
    def _execute_extract_answer(self, context: NodeContext) -> str:
        """执行 EXTRACT_ANSWER 函数"""
        config = self.config.get('extract_answer', {})
        document = context.resolve_template(config.get('document', ''))
        question = context.resolve_template(config.get('question', ''))
        
        if not document or not question:
            raise ValueError('EXTRACT_ANSWER 功能需要配置 document 和 question')
        
        conn = self._get_connection(self.config, context)
        try:
            cursor = conn.cursor()
            sql = "SELECT SNOWFLAKE.CORTEX.EXTRACT_ANSWER(%s, %s)"
            cursor.execute(sql, (document, question))
            row = cursor.fetchone()
            result = row[0] if row else ''
            
            # 解析 JSON 结果
            if isinstance(result, str):
                try:
                    parsed = json.loads(result)
                    if isinstance(parsed, list) and len(parsed) > 0:
                        # 返回第一个答案
                        return parsed[0].get('answer', result)
                except json.JSONDecodeError:
                    pass
            
            return result
        finally:
            conn.close()
    
    @classmethod
    def get_config_schema(cls) -> Dict[str, Any]:
        """获取配置 Schema"""
        return {
            'type': 'object',
            'properties': {
                'connection': {
                    'type': 'object',
                    'title': 'Snowflake 连接',
                    'properties': {
                        'account': {'type': 'string', 'title': 'Account'},
                        'user': {'type': 'string', 'title': 'User'},
                        'password': {'type': 'string', 'title': 'Password', 'format': 'password'},
                        'warehouse': {'type': 'string', 'title': 'Warehouse'},
                        'database': {'type': 'string', 'title': 'Database'},
                        'schema': {'type': 'string', 'title': 'Schema', 'default': 'PUBLIC'},
                        'role': {'type': 'string', 'title': 'Role'},
                    },
                    'required': ['account', 'user', 'password', 'warehouse', 'database'],
                },
                'function': {
                    'type': 'string',
                    'title': '功能类型',
                    'enum': ['complete', 'summarize', 'translate', 'sentiment', 'extract_answer'],
                    'default': 'complete',
                },
                'complete': {
                    'type': 'object',
                    'title': 'COMPLETE 配置',
                    'properties': {
                        'model': {'type': 'string', 'title': '模型', 'default': 'mistral-large'},
                        'prompt': {'type': 'string', 'title': '提示词', 'format': 'textarea'},
                        'system_prompt': {'type': 'string', 'title': '系统提示词', 'format': 'textarea'},
                        'temperature': {'type': 'number', 'title': '温度', 'default': 0.7},
                        'max_tokens': {'type': 'integer', 'title': '最大 Token', 'default': 1024},
                    },
                },
                'summarize': {
                    'type': 'object',
                    'title': 'SUMMARIZE 配置',
                    'properties': {
                        'text': {'type': 'string', 'title': '待摘要文本', 'format': 'textarea'},
                    },
                },
                'translate': {
                    'type': 'object',
                    'title': 'TRANSLATE 配置',
                    'properties': {
                        'text': {'type': 'string', 'title': '待翻译文本', 'format': 'textarea'},
                        'source_language': {'type': 'string', 'title': '源语言', 'default': 'en'},
                        'target_language': {'type': 'string', 'title': '目标语言', 'default': 'zh'},
                    },
                },
                'sentiment': {
                    'type': 'object',
                    'title': 'SENTIMENT 配置',
                    'properties': {
                        'text': {'type': 'string', 'title': '待分析文本', 'format': 'textarea'},
                    },
                },
                'extract_answer': {
                    'type': 'object',
                    'title': 'EXTRACT_ANSWER 配置',
                    'properties': {
                        'document': {'type': 'string', 'title': '文档内容', 'format': 'textarea'},
                        'question': {'type': 'string', 'title': '问题'},
                    },
                },
                'output_variable': {
                    'type': 'string',
                    'title': '输出变量名',
                    'default': 'cortex_result',
                },
            },
            'required': ['connection', 'function'],
        }


@NodeRegistry.register
class SnowflakeCortexAnalystNode(BaseNode, SnowflakeConnectionMixin):
    """
    Snowflake Cortex Analyst 节点
    
    使用自然语言查询数据，自动生成 SQL 并返回结果
    """
    
    node_type = 'snowflake_cortex_analyst'
    node_name = 'Snowflake Cortex Analyst'
    node_category = 'ai'
    node_icon = 'snowflake'
    node_description = 'Snowflake Cortex Analyst - 自然语言查询数据'
    
    inputs = [
        {
            'name': 'question',
            'type': 'string',
            'description': '自然语言问题',
        },
    ]
    
    outputs = [
        {
            'name': 'result',
            'type': 'object',
            'description': '查询结果',
        },
        {
            'name': 'sql',
            'type': 'string',
            'description': '生成的 SQL',
        },
    ]
    
    def execute(self, context: NodeContext) -> NodeResult:
        """执行 Cortex Analyst 查询"""
        start_time = time.time()
        
        try:
            # 获取配置
            question = context.resolve_template(self.config.get('question', ''))
            semantic_model_file = self.config.get('semantic_model_file', '')
            
            if not question:
                return NodeResult(
                    success=False,
                    error='请配置查询问题',
                )
            
            if not semantic_model_file:
                return NodeResult(
                    success=False,
                    error='请配置语义模型文件路径',
                )
            
            # 调用 Cortex Analyst API
            result = self._call_cortex_analyst(context, question, semantic_model_file)
            
            elapsed_time = int((time.time() - start_time) * 1000)
            output_var = self.config.get('output_variable', 'analyst_result')
            sql_var = self.config.get('sql_variable', 'analyst_sql')
            
            return NodeResult(
                success=True,
                output=result,
                output_variables={
                    output_var: result.get('data', []),
                    sql_var: result.get('sql', ''),
                    f'{output_var}_raw': result,
                },
                elapsed_time=elapsed_time,
                metadata={'question': question},
            )
            
        except Exception as e:
            logger.exception(f'Snowflake Cortex Analyst 节点执行失败: {e}')
            elapsed_time = int((time.time() - start_time) * 1000)
            return NodeResult(
                success=False,
                error=str(e),
                elapsed_time=elapsed_time,
            )
    
    def _call_cortex_analyst(
        self,
        context: NodeContext,
        question: str,
        semantic_model: str,
    ) -> Dict[str, Any]:
        """
        调用 Cortex Analyst API
        
        Cortex Analyst 必须通过 REST API 调用，不支持 SQL 函数方式。
        
        支持两种语义模型来源：
        1. Semantic View: database.schema.semantic_view_name (如 AI_TEST.PUBLIC.CAR_AI_TEST)
        2. Stage 文件: @database.schema.stage/file.yaml
        
        Args:
            context: 节点上下文
            question: 用户问题
            semantic_model: 语义模型路径（Semantic View 或 Stage 文件）
        """
        import requests
        
        connection_config = self.config.get('connection', {})
        account = context.resolve_template(connection_config.get('account', ''))
        database = context.resolve_template(connection_config.get('database', ''))
        schema = context.resolve_template(connection_config.get('schema', 'PUBLIC'))
        
        # 获取连接以获取 session token
        conn = self._get_connection(self.config, context)
        
        try:
            # 从连接中获取 REST session token
            # Snowflake Python Connector 可以提供 REST session token
            rest_token = conn.rest.token
            master_token = conn.rest.master_token
            
            # 构建 API URL
            # 处理 account 格式：可能是 xxx.snowflakecomputing.com 或 account_identifier
            if '.snowflakecomputing.com' in account:
                host = account
            else:
                # 从连接获取实际 host
                host = conn.host if hasattr(conn, 'host') else f'{account}.snowflakecomputing.com'
            
            base_url = f"https://{host}"
            api_url = f"{base_url}/api/v2/cortex/analyst/message"
            
            # 构建请求头
            headers = {
                'Content-Type': 'application/json',
                'Accept': 'application/json',
                'Authorization': f'Snowflake Token="{rest_token}"',
            }
            
            # 判断是 Semantic View 还是 Stage 文件
            is_stage_file = semantic_model.startswith('@')
            
            # 构建请求体
            messages = [
                {
                    'role': 'user',
                    'content': [{'type': 'text', 'text': question}]
                }
            ]
            
            if is_stage_file:
                # Stage 文件格式: @database.schema.stage/file.yaml
                payload = {
                    'messages': messages,
                    'semantic_model_file': semantic_model,
                }
            else:
                # Semantic View 格式: database.schema.view_name
                # 使用 semantic_models 数组包含 semantic_view
                payload = {
                    'messages': messages,
                    'semantic_models': [
                        {'semantic_view': semantic_model}
                    ],
                }
            
            logger.info(f'调用 Cortex Analyst API: {api_url}')
            logger.info(f'Payload: {payload}')
            
            response = requests.post(
                api_url,
                json=payload,
                headers=headers,
                timeout=60,
            )
            
            logger.info(f'Cortex Analyst 响应状态: {response.status_code}')
            
            if response.status_code != 200:
                error_text = response.text
                logger.error(f'Cortex Analyst API 错误: {error_text}')
                raise ValueError(f'Cortex Analyst API 调用失败: {response.status_code} - {error_text}')
            
            result = response.json()
            logger.info(f'Cortex Analyst 返回: {result}')
            
            # 解析响应，提取 SQL 和执行结果
            return self._parse_analyst_response(conn, result)
            
        except requests.RequestException as e:
            logger.exception(f'Cortex Analyst REST API 调用失败: {e}')
            raise ValueError(f'Cortex Analyst API 调用失败: {e}')
        finally:
            conn.close()
    
    def _parse_analyst_response(self, conn, result: Dict[str, Any]) -> Dict[str, Any]:
        """解析 Cortex Analyst 响应并执行生成的 SQL"""
        generated_sql = None
        answer_text = None
        
        # 尝试从响应中提取 SQL
        if isinstance(result, dict):
            # 格式1: message.content 数组
            if 'message' in result and 'content' in result['message']:
                content = result['message']['content']
                if isinstance(content, list):
                    for item in content:
                        if isinstance(item, dict):
                            if item.get('type') == 'sql':
                                generated_sql = item.get('statement', item.get('text', ''))
                            elif item.get('type') == 'text':
                                answer_text = item.get('text', '')
                elif isinstance(content, str):
                    answer_text = content
            
            # 格式2: 直接 sql 字段
            elif 'sql' in result:
                generated_sql = result['sql']
            
            # 格式3: choices 数组
            elif 'choices' in result and len(result['choices']) > 0:
                choice = result['choices'][0]
                if 'message' in choice and 'content' in choice['message']:
                    content = choice['message']['content']
                    if isinstance(content, list):
                        for item in content:
                            if isinstance(item, dict):
                                if item.get('type') == 'sql':
                                    generated_sql = item.get('statement', '')
                                elif item.get('type') == 'text':
                                    answer_text = item.get('text', '')
        
        # 如果有生成的 SQL，执行它获取数据
        if generated_sql:
            logger.info(f'执行生成的 SQL: {generated_sql}')
            cursor = conn.cursor()
            try:
                cursor.execute(generated_sql)
                columns = [desc[0] for desc in cursor.description]
                rows = cursor.fetchall()
                data = [dict(zip(columns, r)) for r in rows]
                
                return {
                    'sql': generated_sql,
                    'data': data,
                    'columns': columns,
                    'row_count': len(data),
                    'answer': answer_text,
                }
            finally:
                cursor.close()
        
        # 没有 SQL，返回文本回答
        return {
            'sql': '',
            'data': [],
            'columns': [],
            'row_count': 0,
            'answer': answer_text or str(result),
            'raw_response': result,
        }
    
    @classmethod
    def get_config_schema(cls) -> Dict[str, Any]:
        """获取配置 Schema"""
        return {
            'type': 'object',
            'properties': {
                'connection': {
                    'type': 'object',
                    'title': 'Snowflake 连接',
                    'properties': {
                        'account': {'type': 'string', 'title': 'Account'},
                        'user': {'type': 'string', 'title': 'User'},
                        'password': {'type': 'string', 'title': 'Password', 'format': 'password'},
                        'warehouse': {'type': 'string', 'title': 'Warehouse'},
                        'database': {'type': 'string', 'title': 'Database'},
                        'schema': {'type': 'string', 'title': 'Schema', 'default': 'PUBLIC'},
                        'role': {'type': 'string', 'title': 'Role'},
                    },
                    'required': ['account', 'user', 'password', 'warehouse', 'database'],
                },
                'question': {
                    'type': 'string',
                    'title': '查询问题',
                    'description': '用自然语言描述你想查询的数据',
                    'format': 'textarea',
                },
                'semantic_model_file': {
                    'type': 'string',
                    'title': '语义模型文件',
                    'description': '语义模型文件路径，如 @my_db.my_schema.my_stage/semantic_model.yaml',
                },
                'output_variable': {
                    'type': 'string',
                    'title': '输出变量名',
                    'default': 'analyst_result',
                },
            },
            'required': ['connection', 'question', 'semantic_model_file'],
        }
