"""核心修复逻辑 - 解析 bugs.md，分析冲突，触发 VS Code 扩展"""
import re
import os
import sys
import json
import subprocess
import time
import shutil

TRIGGER_FILE = "_fix_trigger.json"
DONE_DIR = "_fix_tmp"


def parse_bugs(filepath):
    with open(filepath, "r", encoding="utf-8") as f:
        lines = f.readlines()
    bugs = []
    for line_num_0, raw_line in enumerate(lines):
        line = raw_line.strip()
        if re.match(r"^\d+[、.]", line):
            if "[已修复]" in line:
                continue
            desc = re.sub(r"^\d+[、.]\s*", "", line).strip()
            bugs.append({"lineNum": line_num_0 + 1, "desc": desc})
    return bugs


def analyze_conflicts(bugs):
    if len(bugs) <= 1:
        return bugs

    bug_list_text = "\n".join(
        f"- Bug L{b['lineNum']}: {b['desc']}" for b in bugs
    )
    prompt = (
        "请查看当前项目的代码结构，分析以下 bug 列表，判断每个 bug 修复时会涉及哪些文件。"
        "你需要根据 bug 描述在项目中搜索相关代码来确定涉及的文件，不要凭空猜测。"
        "只输出 JSON，不要其他文字。格式：\n"
        '{"bugs": [{"lineNum": 27, "files": ["path/to/file1.py"]}]}\n\n'
        f"Bug 列表：\n{bug_list_text}"
    )
    try:
        result = subprocess.run(
            ["claude", "-p", prompt],
            capture_output=True, text=True, encoding="utf-8", timeout=120
        )
    except Exception as e:
        print(f"预分析调用失败: {e}，所有 bug 将串行执行")
        for b in bugs:
            b["conflictGroup"] = "serial_fallback"
        return bugs

    if result.returncode != 0:
        print("预分析失败，所有 bug 将串行执行")
        for b in bugs:
            b["conflictGroup"] = "serial_fallback"
        return bugs

    return build_conflict_groups(bugs, result.stdout)


def build_conflict_groups(bugs, claude_output):
    json_match = re.search(r'\{.*\}', claude_output, re.DOTALL)
    if not json_match:
        for b in bugs:
            b["conflictGroup"] = "serial_fallback"
        return bugs

    try:
        analysis = json.loads(json_match.group())
    except json.JSONDecodeError:
        for b in bugs:
            b["conflictGroup"] = "serial_fallback"
        return bugs

    file_map = {}
    for item in analysis.get("bugs", []):
        ln = item.get("lineNum")
        files = set(item.get("files", []))
        file_map[ln] = files

    if not file_map:
        for b in bugs:
            b["conflictGroup"] = "serial_fallback"
        return bugs

    # Union-Find
    parent = {b["lineNum"]: b["lineNum"] for b in bugs}

    def find(x):
        while parent[x] != x:
            parent[x] = parent[parent[x]]
            x = parent[x]
        return x

    def union(a, b):
        ra, rb = find(a), find(b)
        if ra != rb:
            parent[ra] = rb

    line_nums = [b["lineNum"] for b in bugs]
    for i in range(len(line_nums)):
        for j in range(i + 1, len(line_nums)):
            li, lj = line_nums[i], line_nums[j]
            files_i = file_map.get(li, set())
            files_j = file_map.get(lj, set())
            if files_i & files_j:
                union(li, lj)

    group_id_map = {}
    gid = 0
    for b in bugs:
        root = find(b["lineNum"])
        if root not in group_id_map:
            group_id_map[root] = f"group_{gid}"
            gid += 1
        b["conflictGroup"] = group_id_map[root]

    group_sizes = {}
    for b in bugs:
        group_sizes[b["conflictGroup"]] = group_sizes.get(b["conflictGroup"], 0) + 1
    for b in bugs:
        if group_sizes[b["conflictGroup"]] == 1:
            b["conflictGroup"] = None

    return bugs


def run():
    from claude_fix_bugs.installer import ensure_installed

    if not os.path.exists("bugs.md"):
        print("错误: bugs.md 不存在")
        sys.exit(1)

    bugs = parse_bugs("bugs.md")
    if not bugs:
        print("bugs.md 中没有未修复的 bug")
        sys.exit(0)

    print(f"发现 {len(bugs)} 个未修复 bug")

    ensure_installed()

    print("正在分析文件依赖...")
    bugs = analyze_conflicts(bugs)

    parallel_bugs = [b for b in bugs if b.get("conflictGroup") is None]
    serial_groups = {}
    for b in bugs:
        g = b.get("conflictGroup")
        if g is not None:
            serial_groups.setdefault(g, []).append(b["lineNum"])
    print(f"  并行: {len(parallel_bugs)} 个独立 bug")
    for g, lns in serial_groups.items():
        print(f"  串行队列 {g}: L{', L'.join(str(x) for x in lns)}")

    trigger_data = {
        "bugs": [
            {
                "lineNum": b["lineNum"],
                "desc": b["desc"],
                "conflictGroup": b.get("conflictGroup"),
            }
            for b in bugs
        ],
    }
    with open(TRIGGER_FILE, "w", encoding="utf-8") as f:
        json.dump(trigger_data, f, ensure_ascii=False, indent=2)

    total = len(bugs)
    print(f"\n已触发 {total} 个 bug 修复任务")
    print("请切换到 VS Code 窗口查看终端")
    print("自动修复失败的 bug 会自动切换为交互模式并通知你")

    max_wait = total * 35 * 60
    waited = 0
    print("\n等待修复完成...", end="", flush=True)
    while waited < max_wait:
        if not os.path.exists(TRIGGER_FILE):
            done_count = sum(
                1 for b in bugs
                if os.path.exists(os.path.join(DONE_DIR, f"done_{b['lineNum']}.txt"))
            )
            if done_count >= total:
                break
        time.sleep(3)
        waited += 3
        print(".", end="", flush=True)

    if waited >= max_wait:
        print(f"\n等待超时（{max_wait // 60}分钟），请手动检查未完成的任务")

    if os.path.exists(DONE_DIR):
        shutil.rmtree(DONE_DIR, ignore_errors=True)

    print("\n完成")
