#!/usr/bin/env python3
"""
重新跑优先级判定 + AI 归纳 + 回写知识库文档（修复版）。
基于已有的 cluster_context JSON 文件，复用 update_summary_doc_as_children。

用法:
  python3 refix_priority_and_summary.py --channel feishu --date 2026-06-06
  python3 refix_priority_and_summary.py --channel wechat --date 2026-06-07
  python3 refix_priority_and_summary.py --channel all --start 2026-06-06 --end 2026-06-10
"""

import sys, os, json, argparse, urllib.request, time
from datetime import datetime, timedelta

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
SKILL_SCRIPT_DIR = os.path.join(SCRIPT_DIR, "..", "skills", "feishu-feedback-sync", "scripts")
sys.path.insert(0, SKILL_SCRIPT_DIR)
import sync_feishu_feedback as fsf
import priority_classifier as pc

CONTEXT_DIR = os.path.join(SCRIPT_DIR, "..", "output", "daily_feedback")

DEEPSEEK_API_KEY = "sk-7cf94305fb12473b956fd2ed2a6db05b"
DEEPSEEK_BASE_URL = "https://api.deepseek.com/v1"
DEEPSEEK_MODEL = "deepseek-v4-pro"

SYSTEM_PROMPT = """你是一个游戏产品的问题归纳助手。你的任务是：
阅读一段来自测试群的多人对话（可能包含多个发言人、多轮讨论），
从中提炼出他们正在讨论的「具体问题是什么」，用一句中文描述清楚。

要求：
1. 只描述问题本身，不要评价或建议
2. 包含关键要素：在哪个端、哪个环节、什么表现
3. 如果对话中有多种说法，优先采用最后确认的描述
4. 输出仅一句中文，不要加任何前缀、编号、引号或换行
5. 如果对话全是无实质内容的闲聊（如"好的""收到"），输出"无明确问题"
6. **严禁**在问题描述中出现任何员工姓名（如江涛、张骜等），人名用"相关人员"替代

输出格式（严格）：直接输出问题描述，无任何额外文字。"""


def load_context(date_str, channel="feishu"):
    prefix = "wechat_cluster_context" if channel == "wechat" else "cluster_context"
    path = os.path.join(CONTEXT_DIR, f"{prefix}_{date_str}.json")
    if not os.path.exists(path):
        return None
    with open(path, "r", encoding="utf-8") as f:
        return json.load(f)


def call_deepseek(system_prompt, user_prompt, max_retries=2):
    body = json.dumps({
        "model": DEEPSEEK_MODEL,
        "messages": [
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": user_prompt},
        ],
        "temperature": 0.3,
        "max_tokens": 1024,
    }).encode()
    for attempt in range(max_retries + 1):
        try:
            req = urllib.request.Request(
                f"{DEEPSEEK_BASE_URL}/chat/completions",
                data=body,
                headers={"Authorization": f"Bearer {DEEPSEEK_API_KEY}", "Content-Type": "application/json"},
                method="POST",
            )
            resp = urllib.request.urlopen(req, timeout=30)
            data = json.loads(resp.read())
            content = data["choices"][0]["message"]["content"].strip()
            return content.strip('"\'""'' \n')
        except Exception as e:
            if attempt < max_retries:
                print(f"   ⚠️ API 重试 {attempt + 1}: {e}")
                time.sleep(2)
            else:
                raise


def build_user_prompt(cluster):
    lines = [f"优先级: {cluster.get('priority', '?')}", f"分类: {cluster.get('category', '?')}",
             f"当前排查结论: {cluster.get('conclusion', '无')}", "", "--- 对话记录 ---"]
    for msg in cluster.get("messages", []):
        sender = msg.get("sender", "?")
        content = msg.get("content", "")
        mtype = msg.get("msg_type", "text")
        t = msg.get("time", "")
        if mtype in ("image", "post_image", "media", "file", "sticker") and not content.strip():
            continue
        if not content.strip():
            continue
        if len(content) > 200:
            content = content[:197] + "..."
        lines.append(f"[{t}] {sender}: {content}")
    return "\n".join(lines)


def strip_names(text, cluster=None):
    import re
    if not text:
        return text
    if cluster:
        for m in cluster.get("messages", []):
            name = m.get("sender", "").strip()
            if name and len(name) >= 2:
                text = text.replace(name, '相关人员')
    surnames = '李王张刘陈杨赵黄周吴徐孙胡朱高林何郭马罗梁宋郑谢韩唐冯于董萧程曹袁邓许傅沈曾彭吕苏卢蒋蔡贾丁魏薛叶阎余潘杜戴夏钟汪田任姜范方石姚谭廖邹熊金陆郝孔白崔康毛邱秦江史顾侯邵孟龙万段雷钱汤尹黎易常武乔贺赖龚文'
    pattern = '[' + surnames + '][一-鿿]'
    content_words = {
        '文件','资源','存在','动画','角色','设计','问题','音频','显示','界面','关卡','课程','内容','配置','重点','引导','模型',
        '测试','环境','部署','灰度','版本','组件','数据','命名','图片','视频','格式','选项','处理','结果','玩家','游戏',
        '开发','项目','报告','任务','状态','进度','确认','反馈','功能','系统','后台','前端','服务','需要','可能','正常',
        '异常','错误','修复','解决','检查','查看','说明','登录','注册','打开','关闭','更新','调试','运行','启动','停止',
        '通过','失败','成功','完成','开始','结束','使用','操作','调整','优化','修改','增加','删除','添加','移除','切换',
        '程序','方式','相关','进入','平板','第四','单元','原生','声音','断断','续续','后台','托管','无法','熏听','加载',
        '消耗','容器','时候','较多','知识','巩固','环节','第一','播放','警报','正确','系统','操作','权限','人员','内核',
    }
    def _replace(m):
        name = m.group(0)
        return '相关人员' if name not in content_words else name
    return re.sub(pattern, _replace, text)


def convert_to_db_rows(cluster):
    return [(
        m.get("message_id", ""), m.get("sender", ""), m.get("msg_type", "text"),
        m.get("content", ""), m.get("media_url", ""), m.get("quote_message_id", ""),
        m.get("time", ""), 0,
    ) for m in cluster.get("messages", [])]


def regenerate_priority_and_descriptions(context_data):
    clusters = context_data.get("clusters", [])
    results = []
    for cluster in clusters:
        idx = cluster.get("index", 0)
        db_rows = convert_to_db_rows(cluster)
        priority_info = pc.compute_final_priority(db_rows)
        cluster["priority"] = priority_info["priority"]
        cluster["priority_info"] = priority_info
        print(f"   #{idx} → {priority_info['emoji']} {priority_info['priority']} ({priority_info['reasoning'][:80]})")
        
        user_prompt = build_user_prompt(cluster)
        try:
            description = call_deepseek(SYSTEM_PROMPT, user_prompt)
        except Exception as e:
            print(f"   ❌ #{idx} API 失败: {e}")
            description = f"[API调用失败: {str(e)[:50]}]"
        
        if not description or not description.strip():
            location = fsf.extract_location_elements(db_rows)
            root_text = db_rows[0][3] if db_rows else ""
            description = fsf.generate_problem_description(db_rows, location, root_text, ai_placeholder=False, placeholder_idx=idx)
            print(f"   ⚠️ AI 空，回退: {description[:50]}")
        else:
            print(f"   📝 {description[:80]}")
        
        description = strip_names(description, cluster=cluster)
        results.append({"index": idx, "description": description, "priority": priority_info["priority"]})
    return results


def build_summary_md(context_data, results):
    clusters = context_data.get("clusters", [])
    desc_map = {r["index"]: r for r in results}
    
    lines = ["## 今日问题归纳", ""]
    grouped = {"P0": {}, "P1": {}, "P2": {}, "P3": {}}
    
    for c in clusters:
        idx = c.get("index", 0)
        info = desc_map.get(idx, {})
        desc = info.get("description", f"[问题{idx}]")
        if desc in ("无明确问题", ""):
            continue
        priority = info.get("priority", c.get("priority", "P2"))
        category = c.get("category", "其他问题")
        grouped[priority].setdefault(category, []).append(desc)
    
    headers = {
        "P0": "⚠️ P0级核心问题（需优先处理）",
        "P1": "⚡ P1级重要问题",
        "P2": "📌 P2级一般问题",
        "P3": "📝 P3级低优先级",
    }
    
    for p_level in ["P0", "P1", "P2", "P3"]:
        cat_map = grouped[p_level]
        if not cat_map:
            continue
        lines.append(f"**{headers[p_level]}**")
        cat_num = 1
        for cat_name, descs in cat_map.items():
            lines.append(f"{cat_num}. {cat_name}")
            for desc in descs:
                lines.append(f"   - {desc}")
            cat_num += 1
        lines.append("")
    
    lines.append("## 今日问题拆解")
    lines.append("")
    
    for c in clusters:
        idx = c.get("index", 0)
        info = desc_map.get(idx, {})
        desc = info.get("description", f"[问题{idx}]")
        priority = info.get("priority", c.get("priority", "P2"))
        
        lines.append(f"### 【{priority}】")
        lines.append(f"**{idx}，问题描述：** {desc}")
        lines.append(f"**当前问题排查结论：** {c.get('conclusion', '暂无结论排查中')}")
        lines.append("")
        
        msgs = c.get("messages", [])
        if msgs:
            lines.append(f'<lark-table rows="{len(msgs)+1}" cols="2" header-row="true" column-widths="120,328">')
            lines.append("  <lark-tr><lark-td>发言人</lark-td><lark-td>对话信息</lark-td></lark-tr>")
            for m in msgs:
                sender = m.get("sender", "?").replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
                content = m.get("content", "").replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
                if len(content) > 500:
                    content = content[:497] + "..."
                lines.append(f"  <lark-tr><lark-td>{sender}</lark-td><lark-td>{content}</lark-td></lark-tr>")
            lines.append("</lark-table>")
        lines.append("")
    
    return "\n".join(lines)


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--channel", default="feishu", choices=["feishu", "wechat", "all"])
    parser.add_argument("--date", help="单日 YYYY-MM-DD")
    parser.add_argument("--start", help="起始日期")
    parser.add_argument("--end", help="结束日期")
    args = parser.parse_args()
    
    channels = ["feishu", "wechat"] if args.channel == "all" else [args.channel]
    
    if args.date:
        dates = [args.date]
    elif args.start and args.end:
        start = datetime.strptime(args.start, "%Y-%m-%d")
        end = datetime.strptime(args.end, "%Y-%m-%d")
        dates = [(start + timedelta(days=i)).strftime("%Y-%m-%d") for i in range((end-start).days + 1)]
    else:
        print("请指定 --date 或 --start/--end")
        sys.exit(1)
    
    for ch in channels:
        label = "微信" if ch == "wechat" else "飞书"
        title_prefix = "微信-" if ch == "wechat" else "飞书-"
        
        # Set parent node
        if ch == "wechat":
            fsf.SUMMARY_PARENT_NODE = "XhtGwjitFizzCNkw8Xzc2IXsnuf"
        else:
            fsf.SUMMARY_PARENT_NODE = "RaL6whoYMijyYHkSlWrc7OLLnBy"
        
        day_summaries = {}
        for d in dates:
            print(f"\n{'='*60}")
            print(f"📋 [{label}] {d}")
            
            ctx = load_context(d, channel=ch)
            if not ctx or not ctx.get("clusters"):
                print(f"   ⚠️ 无数据，跳过")
                continue
            
            print(f"   🔄 重新判定优先级 + AI 归纳 ({len(ctx['clusters'])} 个簇)...")
            results = regenerate_priority_and_descriptions(ctx)
            summary_md = build_summary_md(ctx, results)
            day_summaries[d] = summary_md
        
        if day_summaries:
            print(f"\n📄 写入知识库...")
            fsf.update_summary_doc_as_children(day_summaries, title_prefix=title_prefix)
    
    print(f"\n🎉 完成")


if __name__ == "__main__":
    main()
