import csv
from collections import Counter, defaultdict
from pathlib import Path

from openpyxl import Workbook
from openpyxl.styles import Alignment, Border, Font, PatternFill, Side


ROOT = Path(__file__).resolve().parents[1]
OUTPUT_ROOT = ROOT / "outputs" / "overnight-quality-1780682025651"
SOURCE = OUTPUT_ROOT / "manual-review-sample.csv"
CSV_OUT = OUTPUT_ROOT / "software-client-list-dedup.csv"
XLSX_OUT = OUTPUT_ROOT / "software-client-list-dedup.xlsx"
SUMMARY_OUT = OUTPUT_ROOT / "software-client-list-dedup-summary.md"

HEADERS = [
    "brief编号",
    "策略",
    "排名",
    "平台",
    "博主名称",
    "综合分",
    "brief匹配分",
    "参考风格分",
    "证据加分",
    "证据风险扣分",
    "推荐理由",
    "风险提示",
    "主页链接",
    "人工复核标签",
]

STRATEGY_PRIORITY = {
    "result-first-broad": 50,
    "result-first": 40,
    "video-enhanced": 30,
    "result-first-risk": 20,
    "baseline-live": 10,
}


def to_num(row, key):
    try:
        return float(str(row.get(key, "")).strip() or 0)
    except ValueError:
        return 0.0


def norm(text):
    return " ".join(str(text or "").strip().lower().split())


def dedupe_key(row):
    link = norm(row.get("主页链接"))
    if link:
        return (norm(row.get("brief编号")), norm(row.get("平台")), link)
    return (norm(row.get("brief编号")), norm(row.get("平台")), norm(row.get("博主名称")))


def quality_key(row):
    return (
        STRATEGY_PRIORITY.get(row.get("策略"), 0),
        to_num(row, "综合分"),
        to_num(row, "brief匹配分"),
        to_num(row, "参考风格分"),
        to_num(row, "证据加分"),
        -to_num(row, "证据风险扣分"),
        -to_num(row, "排名"),
    )


def load_rows():
    with SOURCE.open("r", encoding="utf-8-sig", newline="") as handle:
        rows = list(csv.DictReader(handle))
    for row in rows:
        for header in HEADERS:
            row.setdefault(header, "")
    return rows


def dedupe_rows(rows):
    kept = {}
    all_by_key = defaultdict(list)
    for row in rows:
        key = dedupe_key(row)
        all_by_key[key].append(row)
        if key not in kept or quality_key(row) > quality_key(kept[key]):
            kept[key] = dict(row)

    unique_rows = list(kept.values())
    unique_rows.sort(
        key=lambda row: (
            row.get("brief编号", ""),
            -to_num(row, "综合分"),
            -to_num(row, "brief匹配分"),
            -to_num(row, "参考风格分"),
            -to_num(row, "证据加分"),
            to_num(row, "证据风险扣分"),
            row.get("平台", ""),
            row.get("博主名称", ""),
        )
    )

    rank_by_brief = defaultdict(int)
    for row in unique_rows:
        brief = row.get("brief编号", "")
        rank_by_brief[brief] += 1
        row["排名"] = str(rank_by_brief[brief])
        row["人工复核标签"] = ""
    return unique_rows, all_by_key


def write_csv(rows):
    with CSV_OUT.open("w", encoding="utf-8-sig", newline="") as handle:
        writer = csv.DictWriter(handle, fieldnames=HEADERS, extrasaction="ignore")
        writer.writeheader()
        writer.writerows(rows)


def write_xlsx(rows, original_count, duplicate_key_count):
    wb = Workbook()
    ws = wb.active
    ws.title = "去重名单"
    ws.append(HEADERS)
    for row in rows:
        ws.append([row.get(header, "") for header in HEADERS])

    header_fill = PatternFill("solid", fgColor="1F4E78")
    header_font = Font(color="FFFFFF", bold=True)
    thin = Side(style="thin", color="D9E2F3")
    for cell in ws[1]:
        cell.fill = header_fill
        cell.font = header_font
        cell.alignment = Alignment(horizontal="center", vertical="center")
        cell.border = Border(bottom=thin)

    widths = {
        "A": 20,
        "B": 18,
        "C": 8,
        "D": 14,
        "E": 24,
        "F": 10,
        "G": 12,
        "H": 12,
        "I": 10,
        "J": 12,
        "K": 110,
        "L": 85,
        "M": 56,
        "N": 16,
    }
    for col, width in widths.items():
        ws.column_dimensions[col].width = width

    for row in ws.iter_rows(min_row=2):
        for cell in row:
            cell.alignment = Alignment(vertical="top", wrap_text=True)
        for idx in [3, 6, 7, 8, 9, 10]:
            row[idx - 1].alignment = Alignment(horizontal="center", vertical="top", wrap_text=True)

    ws.freeze_panes = "A2"
    ws.auto_filter.ref = ws.dimensions

    summary = wb.create_sheet("去重说明")
    summary_rows = [
        ["项目", "值"],
        ["来源文件", str(SOURCE)],
        ["原始行数", original_count],
        ["去重后行数", len(rows)],
        ["删除重复行数", original_count - len(rows)],
        ["存在重复的博主键数量", duplicate_key_count],
        ["去重口径", "同一 brief编号 + 平台 + 主页链接；没有主页链接时使用 brief编号 + 平台 + 博主名称"],
        ["保留规则", "优先 result-first-broad，其次 result-first、video-enhanced、result-first-risk、baseline-live；同优先级下保留综合分/brief匹配/参考风格/证据加分更高且风险扣分更低的一条"],
        ["排名规则", "去重后按每个 brief 重新从 1 排名"],
    ]
    for item in summary_rows:
        summary.append(item)
    summary.column_dimensions["A"].width = 22
    summary.column_dimensions["B"].width = 130
    for cell in summary[1]:
        cell.fill = header_fill
        cell.font = header_font
    for row in summary.iter_rows():
        for cell in row:
            cell.alignment = Alignment(vertical="top", wrap_text=True)

    wb.save(XLSX_OUT)


def write_summary(rows, original_count, duplicate_key_count):
    brief_counts = Counter(row["brief编号"] for row in rows)
    strategy_counts = Counter(row["策略"] for row in rows)
    lines = [
        "# 软件端去重名单导出说明",
        "",
        f"- 来源：`{SOURCE}`",
        f"- 原始行数：{original_count}",
        f"- 去重后行数：{len(rows)}",
        f"- 删除重复行数：{original_count - len(rows)}",
        f"- 存在重复的博主键数量：{duplicate_key_count}",
        f"- CSV：`{CSV_OUT}`",
        f"- XLSX：`{XLSX_OUT}`",
        "",
        "## 各 brief 行数",
        "",
    ]
    for brief, count in sorted(brief_counts.items()):
        lines.append(f"- {brief}: {count}")
    lines.extend(["", "## 保留策略分布", ""])
    for strategy, count in sorted(strategy_counts.items()):
        lines.append(f"- {strategy}: {count}")
    lines.extend(
        [
            "",
            "## 去重与排序口径",
            "",
            "- 去重口径：同一 `brief编号 + 平台 + 主页链接` 视为同一博主；没有主页链接时用 `brief编号 + 平台 + 博主名称`。",
            "- 保留规则：优先发布策略 `result-first-broad`、`result-first`，再保留诊断策略；同优先级下看综合分、brief 匹配、参考风格、证据加分和风险扣分。",
            "- 排名规则：去重后按每个 brief 重新排序。",
        ]
    )
    SUMMARY_OUT.write_text("\n".join(lines), encoding="utf-8-sig")


def main():
    rows = load_rows()
    unique_rows, all_by_key = dedupe_rows(rows)
    duplicate_key_count = sum(1 for values in all_by_key.values() if len(values) > 1)
    write_csv(unique_rows)
    write_xlsx(unique_rows, len(rows), duplicate_key_count)
    write_summary(unique_rows, len(rows), duplicate_key_count)
    print(f"rows_in={len(rows)}")
    print(f"rows_out={len(unique_rows)}")
    print(f"dropped={len(rows) - len(unique_rows)}")
    print(f"duplicate_keys={duplicate_key_count}")
    print(f"csv={CSV_OUT}")
    print(f"xlsx={XLSX_OUT}")
    print(f"summary={SUMMARY_OUT}")


if __name__ == "__main__":
    main()
