"""
MYSQL_HOST=xxx
MYSQL_USERNAME=xxx
MYSQL_PASSWORD=xxx
MYSQL_DATABASE=xxx
MYSQL_PORT=xxx

以上环境变量已配置在 .env 中。

我要导出一个数据表的某些记录  并添加一些字段。

表名:middle_interaction_component

根据 c_id 过滤数据:
c_id为 7位 字符串   其中 {两位季度编号}{两位单元编号}{三位组件编号}  过滤其中 单元编号部分为 00~20 以及 26 的对应记录   也就是  xx00xxx ~ xx20xxx 以及 xx26xxx 的记录

导出以下字段:
id 
c_type
c_id
title
component_config
related_path
kp_relation_info
created_at
updated_at

新增以下字段:
1. “组件类型”:  根据以下映射  把 c_type 转成中文名:xx互动
{
    "词汇类": {
        "物品互动": "mid_vocab_item",
        "图片互动": "mid_vocab_image",
        "填词互动": "mid_vocab_fillBlank",
        "指令互动": "mid_vocab_instruction"
    },
    "句子类": {
        "对话互动": "mid_sentence_dialogue",
        "语音互动": "mid_sentence_voice",
        "材料互动": "mid_sentence_material",
        "造句互动": "mid_sentence_makeSentence"
    },
    "语法类": {
        "挖空互动": "mid_grammar_cloze",
        "组句互动": "mid_grammar_sentence"
    },
    "发音类": {
        "发音互动": "mid_pron_pron"
    
}

2. “是否关联了知识点”:  如果 kp_relation_info 不为空 且包含至少一个具体的知识点编号 则为 “是”  否则为 “否”
有效关联知识点的一个样例数据:[{"kpId":"0326011","kpType":"sentence","kpTitle":"What does... look like?","kpSkill":"sentence_meaning","kpSkillName":"语义"}]

3. "是否已组课"：  如果 related_path  不为空 则为 “是”  否则为 “否”
一个有效的  related_path  样例: {"packageId":13,"unitId":40,"lessonId":213,"packageIndex":3,"unitIndex":2,"lessonIndex":2}

4. “前置对话”:
component_config 中的 preDialog 字段， 如果不存在 则为 “空”
{"asrPrompt":"","cId":"0326022","cType":"mid_sentence_dialogue","meaning":"语义；语音","mode":"read","postDialog":[{"content":"Leave it to me.","npcId":540,"npcName":"Victoria","type":"npc"}],"preDialog":[{"content":"But do we still have time?","npcId":30,"type":"user"}],"question":{"content":"What if we miss the spaceship?","mode":"read","npcId":30,"type":"user"},"resourceMapping":{"Medic":503},"title":"询问万一错过飞船怎么办"}

5. "后置对话":
component_config 中的 postDialog 字段， 如果不存在 则为 “空”

6. 前置/后置对话中非user角色数量
component_config 中的 preDialog 以及 postDialog 字段中， 统计所有 type 为 npc ,根据 npcId 去重后的角色数量
例如 
---
前置对话：
[{"content":"But do we still have time?","npcId":30,"type":"user"}]
后置对话：
[{"content":"Leave it to me.","npcId":540,"npcName":"Victoria","type":"npc"}]
非user角色数量： 1
---

---
前置对话：
[{"content":"But do we still have time?","npcId":31,"type":"npc","npcName":"Ben"}]
后置对话：
[{"content":"Leave it to me.","npcId":540,"npcName":"Victoria","type":"npc"}]
非user角色数量： 2
---

最终输出一个 excel文档。

"""

import os
import json
from datetime import datetime
import pymysql
import pandas as pd
from dotenv import load_dotenv

load_dotenv()

# 组件类型映射
TYPE_MAP = {
    "mid_vocab_item": "物品互动", "mid_vocab_image": "图片互动", 
    "mid_vocab_fillBlank": "填词互动", "mid_vocab_instruction": "指令互动",
    "mid_sentence_dialogue": "对话互动", "mid_sentence_voice": "语音互动",
    "mid_sentence_material": "材料互动", "mid_sentence_makeSentence": "造句互动",
    "mid_grammar_cloze": "挖空互动", "mid_grammar_sentence": "组句互动",
    "mid_pron_pron": "发音互动"
}

def get_data():
    conn = pymysql.connect(
        host=os.getenv('MYSQL_HOST'), port=int(os.getenv('MYSQL_PORT', 3306)),
        user=os.getenv('MYSQL_USERNAME'), password=os.getenv('MYSQL_PASSWORD'),
        database=os.getenv('MYSQL_DATABASE'), charset='utf8mb4'
    )
    
    # 构建c_id过滤条件
    conditions = [f"c_id LIKE '__{i:02d}___'" for i in range(21)] + ["c_id LIKE '__26___'"]
    where_clause = " OR ".join(conditions)
    
    sql = f"""SELECT id, c_type, c_id, title, component_config, related_path, 
              kp_relation_info, created_at, updated_at 
              FROM middle_interaction_component WHERE {where_clause}"""
    
    df = pd.read_sql(sql, conn)
    conn.close()
    return df

def process_data(df):
    # 组件类型
    df['组件类型'] = df['c_type'].map(TYPE_MAP).fillna(df['c_type'])
    
    # 是否关联知识点
    def check_kp(kp_info):
        if not kp_info: return "否"
        try:
            data = json.loads(kp_info)
            return "是" if isinstance(data, list) and any(item.get('kpId') for item in data) else "否"
        except: return "否"
    
    df['是否关联了知识点'] = df['kp_relation_info'].apply(check_kp)
    
    # 是否已组课
    def check_lesson(path):
        if not path: return "否"
        try: return "是" if json.loads(path) else "否"
        except: return "否"
    
    df['是否已组课'] = df['related_path'].apply(check_lesson)
    
    # 前置/后置对话及NPC统计
    def extract_dialog(config, dialog_type):
        if not config: return "空"
        try:
            data = json.loads(config)
            dialog = data.get(dialog_type, [])
            return json.dumps(dialog, ensure_ascii=False) if dialog else "空"
        except: return "空"
    
    def count_npc(config):
        if not config: return 0
        try:
            data = json.loads(config)
            npc_ids = set()
            for dialog in ['preDialog', 'postDialog']:
                for item in data.get(dialog, []):
                    if item.get('type') == 'npc' and 'npcId' in item:
                        npc_ids.add(item['npcId'])
            return len(npc_ids)
        except: return 0
    
    df['前置对话'] = df['component_config'].apply(lambda x: extract_dialog(x, 'preDialog'))
    df['后置对话'] = df['component_config'].apply(lambda x: extract_dialog(x, 'postDialog'))
    df['前置/后置对话中非user角色数量'] = df['component_config'].apply(count_npc)
    
    return df

if __name__ == "__main__":
    df = get_data()
    df = process_data(df)
    
    filename = f"middle_interaction_component_export_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
    df.to_excel(filename, index=False)
    print(f"导出完成: {filename}")
