from __future__ import annotations

import io
import json
from typing import Any, Dict, Iterable, List


def normalize_result_dicts(results: Iterable[Any]) -> List[Dict[str, Any]]:
    normalized: List[Dict[str, Any]] = []
    for item in results:
        if hasattr(item, "to_dict"):
            normalized.append(item.to_dict())
        elif isinstance(item, dict):
            normalized.append(item)
        else:
            normalized.append(
                {
                    "requirement_uid": getattr(item, "requirement_uid", ""),
                    "verdict": getattr(item, "verdict", ""),
                    "coverage_score": getattr(item, "coverage_score", 0.0),
                    "confidence": getattr(item, "confidence", 0.0),
                    "matched_functions": getattr(item, "matched_functions", []),
                    "covered_points": getattr(item, "covered_points", []),
                    "missing_points": getattr(item, "missing_points", []),
                    "conflict_points": getattr(item, "conflict_points", []),
                    "call_chain_evidence": getattr(item, "call_chain_evidence", []),
                    "suggestion": getattr(item, "suggestion", ""),
                    "raw_judgment": getattr(item, "raw_judgment", {}),
                }
            )
    return normalized


def export_json(results: Iterable[Any]) -> bytes:
    return json.dumps(
        {"results": normalize_result_dicts(results)},
        ensure_ascii=False,
        indent=2,
    ).encode("utf-8")


def export_markdown(results: Iterable[Any]) -> str:
    rows = normalize_result_dicts(results)
    lines = [
        "# 需求代码一致性比对报告",
        "",
        "| 需求 ID | 判定 | 覆盖分 | 置信度 | 匹配函数 | 缺失点 | 建议 |",
        "| --- | --- | ---: | ---: | ---: | ---: | --- |",
    ]
    for item in rows:
        lines.append(
            "| {uid} | {verdict} | {score:.2f} | {confidence:.2f} | {functions} | {missing} | {suggestion} |".format(
                uid=item.get("requirement_uid", ""),
                verdict=item.get("verdict", ""),
                score=float(item.get("coverage_score") or 0),
                confidence=float(item.get("confidence") or 0),
                functions=len(item.get("matched_functions") or []),
                missing=len(item.get("missing_points") or []),
                suggestion=str(item.get("suggestion") or "").replace("|", "/"),
            )
        )

    for item in rows:
        lines.extend(
            [
                "",
                f"## {item.get('requirement_uid', '')} {item.get('requirement_title', '')}",
                "",
                f"- 判定: `{item.get('verdict', '')}`",
                f"- 覆盖分: {float(item.get('coverage_score') or 0):.2f}",
                f"- 置信度: {float(item.get('confidence') or 0):.2f}",
                f"- 建议: {item.get('suggestion') or '-'}",
                "",
                "### 匹配函数",
            ]
        )
        for function in item.get("matched_functions") or []:
            lines.append(
                f"- `{function.get('name')}` {function.get('file')}:{function.get('start_line')} "
                f"(similarity={float(function.get('similarity') or 0):.2f})"
            )
        lines.extend(["", "### 缺失点"])
        for point in item.get("missing_points") or ["-"]:
            lines.append(f"- {point}")
        if item.get("conflict_points"):
            lines.extend(["", "### 冲突点"])
            for point in item.get("conflict_points") or []:
                lines.append(f"- {point}")
    return "\n".join(lines)


def export_excel(results: Iterable[Any]) -> bytes:
    try:
        from openpyxl import Workbook
    except ImportError as exc:
        raise RuntimeError("openpyxl is required to export Excel reports.") from exc

    rows = normalize_result_dicts(results)
    workbook = Workbook()
    sheet = workbook.active
    sheet.title = "Consistency"
    headers = [
        "需求ID",
        "需求标题",
        "需求类型",
        "判定",
        "覆盖分",
        "置信度",
        "匹配函数数量",
        "主要文件",
        "缺失点数量",
        "建议",
    ]
    sheet.append(headers)
    for item in rows:
        functions = item.get("matched_functions") or []
        sheet.append(
            [
                item.get("requirement_uid", ""),
                item.get("requirement_title", ""),
                item.get("requirement_type", ""),
                item.get("verdict", ""),
                item.get("coverage_score", 0),
                item.get("confidence", 0),
                len(functions),
                functions[0].get("file", "") if functions else "",
                len(item.get("missing_points") or []),
                item.get("suggestion", ""),
            ]
        )
    output = io.BytesIO()
    workbook.save(output)
    return output.getvalue()

