import json

# 此类会被跑分服务器继承， 可以在类中自由添加自己的prompt构建逻辑, 除了parse_table 和 run_inference_llm 两个方法不可改动
# 注意千万不可修改类名和下面已提供的三个函数名称和参数， 这三个函数都会被跑分服务器调用
class submission():
    def __init__(self, table_meta_path):
        self.table_meta_path = table_meta_path

    # 此函数不可改动, 与跑分服务器端逻辑一致， 返回值 grouped_by_db_id 是数据库的元数据（包含所有验证测试集用到的数据库）
    # 请不要对此函数做任何改动
    def parse_table(self, table_meta_path):
        with open(table_meta_path,'r') as db_meta:
            db_meta_info = json.load(db_meta)
        # 创建一个空字典来存储根据 db_id 分类的数据
        grouped_by_db_id = {}

        # 遍历列表中的每个字典
        for item in db_meta_info:
            # 获取当前字典的 db_id
            db_id = item['db_id']
            
            # 如果 db_id 已存在于字典中，将当前字典追加到对应的列表
            if db_id in grouped_by_db_id:
                grouped_by_db_id[db_id].append(item)
            # 如果 db_id 不在字典中，为这个 db_id 创建一个新列表
            else:
                grouped_by_db_id[db_id] = [item]
        return grouped_by_db_id

    # 此为选手主要改动的逻辑， 此函数会被跑分服务器调用，用来构造最终输出给模型的prompt， 并对模型回复进行打分。
    # 当前提供了一个最基础的prompt模版， 选手需要对其进行改进
    def construct_prompt(self, current_user_question):
        question_type = current_user_question['question_type']
        user_question = current_user_question['user_question']
        # system_prompt = (
        #     "你是一位精通数据库查询与理论解答的专家，专长在于生成精确且格式正确的SQL查询、单项选择题答案或判断题结论。"
        #     "请严格按照以下指令输出：\n"
        #     "- 对于SQL查询，直接输出无格式装饰的纯净SQL语句，无其他赘述，不要;,结尾。\n"
        #     "- 单项选择题，仅回复正确选项的字母。\n"
        #     "- 判断题，直接回复'True'或'False'。\n"
        #     "无需任何额外说明或解释。"
        # )
        if question_type == 'text2sql':
            # system_prompt = """
            # 任务角色：您是一位专业的数据库查询与理论问题解决专家，专注于构造精准的SQL查询语句。 
            # 输出规范：直接生成符合要求的纯SQL代码段，务必排除任何分号或多余的结束符号。所有回复应严格遵循这一格式标准，杜绝添加任何额外的解释或说明文本。 
            # 执行指南： 
            #     1. 精确解析用户提出的数据查询需求或理论疑问。 
            #     2. 根据解析结果，构建高效且准确的SQL查询指令，确保语法正确且无冗余。 
            #     3. 产出的SQL代码需直接呈现，无需附加说明性文字或标点结束符，以保证响应内容的纯粹性与实用性。
            # """
            system_prompt = """
            你已被设定为一位数据库查询与理论问题解答权威，擅长生成精准格式的SQL查询、迅速判定单项选择题答案及明确给出判断题结论。
            请遵守以下精确输出规则：直接输出无多余修饰的纯SQL语句，确保不附加任何分号或结束符号。 
            请确保所有响应严格遵照上述规范，避免任何额外的说明或阐述。
            """
        if question_type == 'multiple_choice':
            system_prompt = """您扮演的是一位数据库查询与理论领域的专家，擅长构造精准的SQL查询语句、迅速确定单项选择题的正确答案，以及对判断题给予确切的结论。请严格遵照以下格式进行回应： - **SQL查询请求**：直接输出无任何格式修饰的纯SQL代码，无须添加如```sql```之类的前后缀。 - **单项选择题**：仅需回复代表正确选项的字母，无需其他内容。 - **判断题**：直接以'True'或'False'作答，不需提供解释或理由。 请确保所有回复均紧扣上述规范，避免添加任何额外的说明或解析。"""
        if question_type == 'true_false_question':
            system_prompt = """
            你已被设定为一位数据库查询与理论问题解答权威，擅长生成精准格式的SQL查询、迅速判定单项选择题答案及明确给出判断题结论。
            请遵守以下精确输出规则： 
            1. 针对SQL查询需求，直接输出无多余修饰的纯SQL语句，确保不附加任何分号或结束符号。 
            2. 遇到单项选择题，仅需反馈正确选项的字母标识，无需其他内容。 
            3. 处理判断题时，直接以'True'或'False'清晰表达结论，排除所有解释性文字。 
            请确保所有响应严格遵照上述规范，避免任何额外的说明或阐述。
            """
        if question_type == 'android_malware_detection': 
            system_prompt = """
            任务指令：作为APK安全分析专家，依据用户提交的APK权限列表，判断其安全性。 
            输入要求：请用户提供APK的完整权限列表。 
            输出格式：简化结果输出，根据分析直接输出数字代码表示APK性质： - 输出“0”代表APK为良性，无安全威胁。 - 输出“1”代表APK疑似恶意，存在安全隐患。 
            分析准则： 
                1. 深入分析用户提供的权限列表，对照已知恶意软件的典型权限特征。 
                2. 综合评估权限组合是否存在非必要或过度索取的情况，以此作为判定依据。 
                3. 仅依据权限分析结果决定输出，不对结论进行详细说明或提供额外信息。
            """
        # 请严格遵循此规范，避免在回答中掺杂任何额外的解释性内容。"""
        if question_type == 'text2sql':
            db_id = current_user_question['db_id']
            cur_db_info = self.parse_table(self.table_meta_path)[db_id]
            for db_info in cur_db_info:
                # 解析数据库信息
                db_id = db_info['db_id']
                tables_info = {}
                column_map = {}  # 用于存储所有列的映射 {table_index: {column_index: column_name}}
                
                # 遍历表信息
                for table_index, table_name in enumerate(db_info['table_names_original']):
                    columns = [col[1] for col in db_info['column_names_original'] if col[0] == table_index]
                    table_info = {
                        '列': columns,
                        '主键': [columns[key] for key in db_info['primary_keys'] if key >= 0 and key < len(columns)],
                        '外键': []
                    }
                    # 构建列的映射
                    column_map[table_index] = {i: col for i, col in enumerate(columns)}
                    tables_info[table_name] = table_info
                
                # 处理外键，确保它们与正确的表相关联
                for key, linked_key in db_info['foreign_keys']:
                    if key >= 0 and linked_key >= 0:
                        # 确定外键和关联列所在的表
                        src_table_index = key // max(len(cols) for cols in column_map.values())
                        dst_table_index = linked_key // max(len(cols) for cols in column_map.values())
                        
                        # 获取列名
                        src_column_name = column_map[src_table_index][key % len(column_map[src_table_index])]
                        dst_column_name = column_map[dst_table_index][linked_key % len(column_map[dst_table_index])]
                        
                        # 添加外键信息
                        tables_info[db_info['table_names_original'][src_table_index]]['外键'].append(f"{src_column_name} (关联到{db_info['table_names_original'][dst_table_index]}表的{dst_column_name})")
                
                # 构建输出格式
                db_output = f"数据库ID：{db_id}\n"
                db_output += "表格：\n"
                for table_name, info in tables_info.items():
                    db_output += f"{table_name}\n"
                    db_output += f"列：{', '.join(info['列'])}\n"
                    db_output += f"主键：{', '.join(map(str, info['主键']))}\n"
                    db_output += f"外键：{', '.join(info['外键'])}\n"
                    db_output += "\n"
            # 强调纯净SQL输出的要求，并在用户问题中明确期望的输出结构
            # user_prompt = f"""
            # 任务指令：设计一个精确的SQL查询以从指定数据库结构中抽取用户请求的数据。确保输出仅为纯净、无注释的SQL代码。 数据库结构概述： ```plaintext {cur_db_info} ``` 问题摘要：`'{user_question}'` 生成策略： 1. **深入分析数据库架构**：细致研究提供的数据库表结构及其字段，识别表间关联。 2. **精准理解需求**：基于用户问题`'{user_question}'`，明确查询目标，包括特定数据需求、过滤条件、排序规则及分组要求。 3. **构建有效SQL查询**：运用标准SQL语法构造查询，直接指向并提取符合所有指定条件的记录。 4. **确保代码纯净性**：产出的SQL代码不得包含任何内嵌的注解或额外文字说明，仅保留可执行的查询指令。 最终产出应为一条可以直接在数据库上执行的SQL语句，旨在高效且准确地解决用户的查询需求。
            # """
            # user_prompt = (
            #     f"根据给定的数据库结构和用户提出的问题，设计一个精确的SQL查询语句以提取所需数据。确保输出结果仅为有效的SQL代码，不包含任何附加说明或解释。"
            #     f"面对数据库结构如下：\n{cur_db_info}\n"
            #     f"请针对问题：'{user_question}' 生成精确SQL查询，确保输出为纯净SQL语句，无任何其他文本。"
            #     """
            #     生成指南： 
            #     1. 仔细分析数据库结构中提供的数据库表结构和字段详情，理解各表之间的关联关系。 
            #     2. 精确解读问题，明确用户所需查询的具体数据及任何过滤、排序或分组要求。 
            #     3. 使用标准的SQL语法编写查询语句，直接从相关表中提取满足条件的数据记录。 
            #     4. 避免在SQL查询中嵌入注释或额外的文字描述，保证输出结果为纯净、可执行的SQL代码段。 
            #     """
            # )
            # user_prompt  = f"根据给定的数据库结构和用户提出的问题，设计一个精确的SQL查询语句以提取所需数据。确保输出结果仅为有效的SQL代码，不包含任何附加说明或解释。 数据库结构概览：{cur_db_info} 问题摘要： ```plaintext {user_question} ``` 生成指南： 1. 仔细分析`{cur_db_info}`中提供的数据库表结构和字段详情，理解各表之间的关联关系。 2. 精确解读`{user_question}`，明确用户所需查询的具体数据及任何过滤、排序或分组要求。 3. 使用标准的SQL语法编写查询语句，直接从相关表中提取满足条件的数据记录。 4. 避免在SQL查询中嵌入注释或额外的文字描述，保证输出结果为纯净、可执行的SQL代码段。 请依据上述指南构造SQL查询。"
            # user_prompt = f"""
            #     作为一名专业的数据分析师及SQL专家，请依据所提供的数据库表结构详情与用户的具体查询需求，直接生成精准的SQL查询代码段。过程中无须展开分析步骤或提供额外说明，输出内容应为无任何前缀、纯净的SQL指令。 
            #     **任务关键点：** 
            #         1. **深入理解需求：**确保完全领悟用户所提出的查询需求。 
            #         2. **表信息透析：**详细审查数据库表结构，把握与需求相关的所有字段及关联。 
            #         3. **构建查询逻辑：**直接在脑内构建出符合需求的SQL查询逻辑。 
            #         4. **直接输出SQL：**无需逐步解析或添加任何注释，直接输出最终的SQL查询命令。 
            #     **数据库表信息：** ``` {db_output} ``` 
            #     **用户查询需求：** ``` {user_question} ``` 
            #     **请在此处直接输出优化后的SQL查询语句：**
            #     """
            user_prompt = f"""
                你现在是一位数据分析师和SQL专家。你的目标是根据提供的表信息和用户需求，生成精确的SQL查询语句。请遵循以下步骤：
                1. 仔细阅读并理解用户需求，确保完全把握需求的意图。
                2. 结合表信息，彻底理解需求的每个细节，识别出需求中的关键信息点。
                3. 基于需求和表信息，运用逻辑分析，构造准确的SQL查询语句。
                4. 运行自我检查三次，确保SQL语句的准确性。如果发现问题，自动进行修复。
                5. 最终，输出纯净的SQL代码，不包含任何解释或附加信息。
                表信息如下：{cur_db_info}
                用户需求：{user_question}
                请在下方输出SQL查询语句：
                """
                 # 输出的SQL代码应遵循以下格式，无需多余修饰：
                #     SELECT [需要选择的列名列表, 可以使用逗号分隔] FROM [表名] [JOIN [类型] [其他表名] ON [本表连接列] = [其他表连接列] [可选，如有多个JOIN则依次列出]] WHERE [筛选条件, 使用AND/OR逻辑连接多个条件] [GROUP BY [分组依据的列名, 可选]] [HAVING [分组后的筛选条件, 可选]] [ORDER BY [排序依据的列名, ASC/DESC, 可选]] LIMIT [返回结果的最大数量, 可选]]
            # user_prompt = (
            #     f"针对数据库结构：{cur_db_info}，需解决的问题为：'{user_question}'。\n"
            #     "请直接输出无多余格式的SQL查询，无需前缀如```sql，仅需纯净的SQL语句。"
            #     # "语句里面不要DISTINCT"
            #     "不要有多余的结尾。"
            # )
            # user_prompt = f"面对数据库结构：{cur_db_info}，用户请求：{user_question}, 不要给我```sql这种，直接输出正确运行的纯净SQL查询作为答案，无其他赘述。"
            # user_prompt = (
            #     f"针对数据库结构：{cur_db_info}，需解决的问题为：'{user_question}'。\n"
            #     "请直接输出无多余格式的SQL查询，无需前缀如```sql，仅需纯净的SQL语句。"
            #     "语句里面不要DISTINCT"
            # )
            # user_prompt = f"数据库格式为：{cur_db_info}，查询问题：{user_question}, 直接输出SQL语句，无其他赘述。直接以文本形式给出SQL语句即可，不要给我```sql这种，不要;,结尾。"
        elif question_type == 'multiple_choice':
            options = "\n".join(f"{chr(i+65)}. {opt}" for i, opt in enumerate(
                (current_user_question['optionA'], 
                current_user_question['optionB'],
                current_user_question['optionC'],
                current_user_question['optionD']), 0))
            # options = "A." + current_user_question['optionA'] + "B." + current_user_question['optionB']+ "C." + current_user_question['optionC']+ "D." + current_user_question['optionD']
            # 明确指示仅需回复选项字母
            # user_prompt = f"""
            # 你是一位精通数据库查询与理论解答的专家，处理单项选择题查询，基于用户提供的问题和选项，精确给出正确答案。
            # 回答格式：直接输出正确选项的字母，不得包含任何其他文字或解释。 
            # 你需要四个步骤来执行这个任务： 
            # 1. 仔细研读问题，确保对问题的意图有全面把握。
            # 2. 逐一审查所有选项，依据问题的详细要求筛选。
            # 3. 运用逻辑思维，对比分析选项，确定最符合题意的答案。
            # 4. 直接输出正确选项的字母，不附带任何解释或附加信息。
            # 请确保回复完全符合上述格式要求。
            # 示例输入应用： ``` 单项选择题详情：用户输入：在SQL中,与“NOT IN”等价的操作符是什么？选项： A、<dgt;ALL；B、<>SOME；C、=SOME；D、=ALL ``` 预期回答格式： ``` A ```
            # 单项选择题详情：{user_question} 选项： {options}
            # """
            # user_prompt = f"""单项选择题响应。 用户问题细节：{user_question} 选项列表： {options} 回答要求：严格遵循以下格式直接回复，仅包含正确选项的字母，不添加任何额外文字或说明。"""
            user_prompt = f"""
            你现在是一位答题专家，负责处理单项选择题。你的目标是根据用户的问题和提供的选项列表，确定正确答案。请遵循以下步骤：

            1. 仔细阅读用户问题，确保理解问题的意图。
            2. 检查提供的选项列表，确保每个选项都是有效的，并且格式正确。
            3. 确定问题和选项之间是否存在逻辑一致性，确保问题可以由提供的选项回答。
            4. 识别正确答案，并确保它是唯一的。
            5. 如果发现问题或选项无效或存在歧义，自动进行修复或调整，以确保可以确定正确答案。
            6. 运行自我检查三次，确保答案的准确性和格式的正确性。
            7. 最终，仅输出正确答案的字母，不包含任何额外文字或说明。

            用户问题细节：{user_question}
            选项列表：{options} 

            请在下方输出正确答案的字母：
            """

            # user_prompt = f"""
            # 任务指令：针对单项选择题进行响应。根据用户提出的问题详情及给定的选项列表，选出正确答案并严格按指定格式返回。 
            # 回答格式：直接输出正确选项的字母，不得包含任何其他字符或说明。 
            # 处理步骤： 
            #     1. 认真分析${user_question}的具体内容，确保理解问题核心。 
            #     2. 检视${options}中的每一个选项，对比题目需求，识别出正确答案。 
            #     3. 依据回答要求，仅输出正确选项的字母，例如“A”、“B”等，不可附加任何解释或多余信息。
            # """

            # user_prompt = f"""
            # ### 精准选择题解答指引

            # #### 目标
            # 精确识别并直接回复用户提出的选择题的正确答案。

            # #### 指南（CRISPE框架）
            # - **清晰性**：确保充分理解问题的核心，避免歧义。
            # - **相关性**：聚焦于问题本身及所提供的选项，剔除非关键信息。
            # - **具体性**：回答仅限于正确选项的字母标识，无额外说明。
            # - **精准性**：遵守回答格式，仅输出正确选项的字母（A、B、C、D）。
            # - **实用性**：采用系统性的思考流程，确保答案准确无误。
            # - **效率性**：迅速且直接地提供答案，不拖延。

            # #### 思考链（COT）步骤
            # 1. **深入理解**：仔细研读问题（{user_question}），确保对问题的意图有全面把握。
            # 2. **选项评估**：逐一审查所有选项（{options}），依据问题的详细要求筛选。
            # 3. **逻辑推理**：运用逻辑思维，对比分析选项，确定最符合题意的答案。
            # 4. **精简回复**：直接输出正确选项的字母，不附带任何解释或附加信息。

            # 请务必遵循以上准则，确保回复格式精确无误。
            # """
        elif question_type == 'true_false_question':
            # 简洁明了地要求True或False的回答
            # user_prompt = (
            #     f"判断题内容：{user_question}\n"
            #     "请直接回复'True'或'False'，无其他说明。"
            # )
            # user_prompt = f"""根据用户提供的判断题内容，直接给出答案。 格式要求：仅回复 'True' 或 'False'，无需附带任何额外解释或内容。 处理步骤： 1. 理解题目：仔细阅读并解析 "{user_question}" 中的判断题内容。 2. 作出判断：基于题目信息，确定其陈述是否正确。 3. 回复答案：根据判断结果，简单回复 'True' 表示陈述正确，'False' 表示陈述错误。 注意：确保回复严格遵循指定格式，避免添加任何说明性文字。"""
            # user_prompt = f"""针对用户提交的判断题，迅速分析并给出确切答案，形式上仅限于'True'或'False'，无需任何附加论述或理由阐述。 执行步骤： 1. **深入解析题目**：透彻理解题目文本${user_question}的所有细节与逻辑，确保全面掌握题意。 2. **严谨判断真假**：根据题目陈述，直接评估其真实性质，不偏离题目本身的内容进行推理。 3. **标准化反馈**：依据判断结论，直接输出'True'表示陈述为真，'False'表示陈述为假，确保回复内容纯净，无任何其他字符或说明介入。 **关键规范重申**： - 确保回复严格符合'True'或'False'的格式要求。 - 在任何情况下，避免在最终答案中掺杂解释、理由或是其他非指定字符。"""
            # user_prompt = f"""针对用户提交的判断题，直接输出答案为'True'或'False'，无须附加解释。 处理指南： 1. **理解题目内容**：深入分析提供的判断题文本`{user_question}`，确保完全把握题目所述信息。 2. **作出精准判断**：依据题目表述，严格判断其陈述的真实性。 3. **回复格式固定**：根据判断结果，直接回复'True'表示陈述正确，'False'表示陈述错误，严禁在答案中夹杂任何额外文字或说明。 **核心要点强调**： - 严格遵守回复格式，仅输出'True'或'False'。 - 避免在答案中包含任何解释性或辅助性内容。"""
            # user_prompt = f"""针对用户提交的判断题，迅速分析并直接输出标准化答案（'True'或'False'），无需任何附加解析或说明。 处理流程： 1. **深入解析题目**：透彻理解题目文本`{user_question}`的每一个细节，确认题干中的所有信息要点。 2. **严谨判断事实**：基于题目内容，实施严密逻辑分析，确定陈述是否符合事实，无误则为'True'，否则为'False'。 3. **标准化反馈**：严格遵循格式要求，仅输出纯净答案——'True'表示陈述准确无误，'False'表示存在错误。 **核心规则重申**： - 确保输出不偏离规定的二元答案格式：'True'或'False'。 - 强制排除任何解释性、辅助性词汇或句子于最终回复之外，保持答案精简纯粹。"""
            # user_prompt = f"判断题内容为:{user_question}，直接反馈True或False作为答案，无其他赘述。"
            # user_prompt = f"""
            # 根据用户提交的判断题，直接输出结论为'True'或'False'，无需任何解释或其他附加信息。 
            # 回答格式规范： - 直接响应答案，仅限于'True'或'False'，确保满足用户对于简化回答的需求。 
            # - 对判断题内容进行严谨分析，确认无误后给出最终判断。 
            # 处理流程： 
            # 1. 仔细阅读并理解判断题内容`{user_question}`，确保完全把握题目意图。 
            # 2. 根据题目逻辑或事实基础，作出准确判断。 
            # 3. 按照规定格式回复，绝对避免在答案中掺杂任何说明性或辅助性文字。 
            # 请严格按照上述指南操作，维持回答的一致性和准确性。"""
            user_prompt = f"""
            你现在是一位数据库查询与理论问题解答权威。你的目标是针对用户提交的判断题，进行迅速分析并给出确切答案。请遵循以下步骤：

            1. 仔细研读问题，确保对问题的意图有全面把握。
            2. 透彻理解题目文本的每一个细节，确认题干中的所有信息要点。
            3. 识别问题中的关键词，如“所有”或“任何”，并检查是否存在任何例外情况。如果存在例外，则命题为假；如果不存在例外，命题为真。
            4. 基于题目内容，实施严密逻辑分析，确定陈述是否符合事实。
            5. 自我检查三次，确保答案的准确性和格式的正确性。如果发现问题，自动进行修复。
            6. 直接输出'True'或'False'，不附带任何解释或附加信息。
            示例：```判断题内容：'GROUP BY 语句可以与任何SQL函数一起使用。答案：'False'```
            这个示例选择False是因为GROUP BY 语句在 SQL 查询中主要用于与聚合函数一起使用，而不是与所有 SQL 函数。
            判断题内容：{user_question}

            请在下方输出答案：
            """
            # user_prompt = f"""根据用户提供的判断题内容，直接给出答案。 格式要求：仅回复 'True' 或 'False'，无需附带任何额外解释或内容。 处理步骤： 1. 理解题目：仔细阅读并解析 "{user_question}" 中的判断题内容。 2. 作出判断：基于题目信息，确定其陈述是否正确。 3. 回复答案：根据判断结果，简单回复 'True' 表示陈述正确，'False' 表示陈述错误。 注意：确保回复严格遵循指定格式，避免添加任何说明性文字。"""
            # 示例输入应用： ``` 判断题内容：数据库中的索引可以加速数据的检索，但不会影响数据的插入速度。``` 预期回答格式： ``` False ```
        elif question_type == 'android_malware_detection': 
            user_prompt = f"""
            你已被设定为一位根据APK的permission识别恶意APK的专家，擅长根据APK的permission明确给出结论。
            输出格式：直接输出0或1，0表示良性APK，1表示恶意APK，不附带任何解释或附加信息。
            APK的权限列表为：{user_question}
            直接输出0或1表示答案，不附带任何解释或附加信息。
            """
        # messages = [{"role": "user", "content": user_prompt.strip()}]
        messages = [{"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt.strip()}]
        return messages
    # 此方法会被跑分服务器调用， messages 选手的 construct_prompt() 返回的结果
    # 请不要对此函数做任何改动
    def run_inference_llm(self, messages):
        pass