#!/usr/bin/env python3
"""Build a coverage summary for template-based tender extraction."""

from __future__ import annotations

from pathlib import Path

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


ROOT = Path(__file__).resolve().parents[1]
OUTPUT = ROOT / "docs" / "deliverables" / "20260615-template-coverage-summary.xlsx"
TEMPLATE = ROOT / "docs" / "templates" / "tender-detail-template" / "【2025】海淀区校园食安项目.xlsx"

FONT = "Microsoft YaHei"
BLUE = "1F4E79"
LIGHT_BLUE = "D9EAF7"
GREEN = "E2F0D9"
YELLOW = "FFF2CC"
RED = "FCE4D6"
GRAY = "F4F6F8"
WHITE = "FFFFFF"
BORDER = Border(
    left=Side(style="thin", color="B7C9DA"),
    right=Side(style="thin", color="B7C9DA"),
    top=Side(style="thin", color="B7C9DA"),
    bottom=Side(style="thin", color="B7C9DA"),
)


TEMPLATE_ITEMS = [
    ("1", "项目基本信息/公告链", "项目名称、编号、采购人、阶段、金额、关键日期、公告/中标/合同链接。"),
    ("2", "产品清单/设备清单", "按模板列分项名称、制造商、品牌、规格型号、单价、数量、金额。"),
    ("3", "软件端详细技术参数", "学校端、教委端、监管端、移动端、运维端、视频平台、AI汇聚、数据前置库、接口开发等模块级功能。"),
    ("4", "硬件设备参数", "摄像机、交换机、NVR、硬盘、AI终端、传感器、网关、蒸烤箱等硬件型号和关键参数。"),
    ("5", "公司/供应商资质", "ISO、软著、CMA检测报告、施工/服务资质、联合体、中小企业、信用和禁入限制等。"),
    ("6", "评分标准/评分情况", "报价、商务、技术参数、技术方案、实施、培训、售后、最终得分或排名。"),
    ("7", "建设范围/学校清单", "覆盖学校、分校址、地址、工程/设备/系统建设范围、交付周期。"),
    ("8", "3家投标公司名单", "至少前三名候选/投标/中标公司、报价、排名、资格能力。"),
    ("9", "中标原因/竞品分析", "为什么中标：价格、技术、资质、业绩、交付、风险和适配场景。"),
]


ORIGINAL_PROJECTS = [
    {
        "name": "延庆区2026年度北京市中小学食堂提升项目",
        "summary": "这个项目一共要抓 9 个，我现在项目来源能确认抓到 1 个，缺 8 个；其余内容只能用模板参考，不算抓到。",
        "count": 1,
        "items": {
            "1": ("✓", "项目名称、采购单位、项目编号、阶段、采购目标可确认。"),
            "2": ("△", "只确认设备更新提升/智慧食堂建设，未披露清单、型号、单价。"),
            "3": ("△", "只确认智慧食堂方向，软件模块为模板参考。"),
            "4": ("△", "只确认设备符合相关标准，未披露硬件型号参数。"),
            "5": ("△", "只披露设备符合相关标准，正式供应商资格未披露。"),
            "6": ("✗", "采购意向阶段未披露评分标准或评分结果。"),
            "7": ("△", "用户表写 37 所学校，但未披露逐校清单/地址。"),
            "8": ("✗", "未到投标/候选披露阶段，无三家公司名单。"),
            "9": ("✗", "无中标结果，无法分析中标原因。"),
        },
        "source": "乙方宝采购意向 + tender-intel-ai 本机底稿",
    },
    {
        "name": "昌平区中小学校园食堂质量提升智慧食堂设备购置项目",
        "summary": "这个项目一共要抓 9 个，我现在项目来源能确认抓到 2 个，缺 7 个；关联工程信息不能替代同名设备包的完整招标信息。",
        "count": 2,
        "items": {
            "1": ("✓", "项目名称、区域、预算、计划时间、核心方向可由用户总表确认。"),
            "2": ("△", "只确认 67 所学校设备购置方向，未披露具体产品清单。"),
            "3": ("✓", "用户表明确智能监管、膳食营养、安全供应三大软件/体系方向，但模块参数仍需采购文件。"),
            "4": ("△", "设备购置包未披露硬件型号；关联工程只披露施工范围。"),
            "5": ("△", "关联工程披露施工总承包/建造师资质，但设备包资质未披露。"),
            "6": ("✗", "同名设备包无评分标准/评分结果；关联工程资格预审已终止。"),
            "7": ("△", "确认 67 所学校和若干场景，但未披露逐校清单/地址。"),
            "8": ("✗", "资格预审已终止且尚未评审，无三家公司名单。"),
            "9": ("✗", "无中标结果，无法分析中标原因。"),
        },
        "source": "用户总表 + 北京公共资源交易服务平台关联工程公告",
    },
    {
        "name": "海淀区中小学第二批智慧食堂项目",
        "summary": "这个项目一共要抓 9 个，我现在项目来源能确认抓到 5 个，缺 4 个；主要缺完整软件功能、逐校范围、完整三家公司和中标原因细分。",
        "count": 5,
        "items": {
            "1": ("✓", "项目编号、交易编号、采购人、预算/中标金额、阶段可确认。"),
            "2": ("✓", "中标公告披露两项万能蒸烤箱的型号、数量、单价、总价。"),
            "3": ("✗", "公开口径为设备采购，未披露独立软件功能。"),
            "4": ("✓", "万能蒸烤箱型号、数量、价格已披露，但更细性能参数仍需中标文件。"),
            "5": ("✓", "政府采购法第二十二条、中小企业、联合体等资格条件可确认。"),
            "6": ("✓", "中标供应商综合评分 88.14 分可确认，评分细则未披露。"),
            "7": ("△", "确认中小学食堂设备采购，但未披露逐校清单/地址。"),
            "8": ("△", "只披露中标供应商，未披露另外两家投标公司。"),
            "9": ("△", "可推断价格/供货/综合评分胜出，但评标报告未公开，不能完整还原中标原因。"),
        },
        "source": "北京市公共资源交易服务平台招标公告 + 中标公告镜像 + 本机底稿",
    },
]


FULL_CANDIDATES = [
    {
        "name": "南京地铁5号线工程新线食堂智能结算设备采购",
        "why": "公开候选人页面直接披露前三名、报价、交货期、资格能力、无效投标、所有有效投标人的商务/技术/报价/其他/总分和业绩；是最适合按模板做全量样例的项目。",
        "coverage": "9/9 可做全量或接近全量",
        "companies": "南京小牛智能科技有限公司；江苏移动信息系统集成有限公司；浙江云澎科技有限公司",
        "key_data": "中标结果 305.010000 万元；南京小牛总分 94.49；江苏移动 87.69；浙江云澎 84.94；另有多家有效投标人得分。",
        "sources": "候选公示 https://njggzy.nanjing.gov.cn/njweb/gchw/070003/20241101/b5cbf419-d1d5-48cb-93ac-1161cd26280b.html\n结果公示 https://njggzy.nanjing.gov.cn/njweb/gchw/070004/20241210/34070c31-fcac-441c-89c2-ad9706ecef1c.html",
        "next": "可直接生成全量模板版 Excel；再补招标文件原文可完善设备技术参数。"
    },
    {
        "name": "中信银行杭州分行智慧食堂软硬件服务商集采入围项目",
        "why": "公开招标公告披露预算、服务范围、资格要求；候选公示披露 5 家入围候选和 16 类智慧食堂软硬件单价。",
        "coverage": "8/9 可做全量；评分细则需招标文件补齐",
        "companies": "常州勤网信息科技有限公司；南京小牛智能科技有限公司；杭州青橄榄网络技术有限公司（另有浙江云澎、正元智慧）",
        "key_data": "预算 1000 万元；服务期 2 年；产品包括人脸识别双面屏终端、称重计量一体机、绑盘机、智慧餐台、智能保温备餐台、速通门、人脸识别机、智慧餐卡等。",
        "sources": "招标公告 https://ebid.cfhc.citic/cms/default/webfile/ywgg1/20250523/1110611760571744256.html\n候选公示 https://ebid.cfhc.citic/cms/default/webfile/ywgg2/20250605/1115365101285670912.html",
        "next": "可生成全量设备/价格/供应商模板；若要评分标准，需下载或购买招标文件。"
    },
    {
        "name": "中国农业银行广东省分行智慧食堂场景建设设备项目",
        "why": "公开招标公告披露预计采购金额、6 类设备最高限价和权重、资格要求；候选公示披露 5 名候选人和投标单价。",
        "coverage": "8/9 可做全量；评分细则需招标文件补齐",
        "companies": "广电运通集团股份有限公司；深圳怡化电脑股份有限公司；广州市派客朴食信息科技有限责任公司（另有佳都科技、海康威视）",
        "key_data": "预计采购金额 3800 万元（不含税）；不多于 4 家中标供应商；设备包括高配桌面/壁挂、基础桌面/壁挂、低配手持、空白卡。",
        "sources": "招标公告 https://e.sinochemitc.com/cms/channel/ywgg1fw/154689.htm\n候选公示 https://e.sinochemitc.com/cms/channel/ywgg2fw/155952.htm",
        "next": "可生成全量设备/价格/候选供应商模板；若要评分细则，需农银 e 采平台招标文件。"
    },
]


FULL_SCRAPED_PROJECTS = [
    {
        "name": "南京地铁5号线工程新线食堂智能结算设备采购",
        "got": 6,
        "partial": 3,
        "missing": 0,
        "summary": "这个项目一共要抓 9 个，现在确认抓到 6 个，另外 3 个部分抓到；没有完全空缺项，主要缺招标文件里的详细产品/软件/硬件参数。",
        "file": "docs/deliverables/20260615-full-candidate-tender-details/01-南京地铁5号线工程新线食堂智能结算设备采购.xlsx",
        "items": {
            "1": ("✓", "项目名称、编号、评标办法、中标人、中标价格和工期可确认。"),
            "2": ("△", "可确认标段为食堂智能结算设备采购，但公开页未列设备型号清单。"),
            "3": ("△", "可按智慧结算场景拆解软件模块，但公开页未披露模块级参数。"),
            "4": ("△", "可确认智能结算设备采购，未披露硬件型号和技术指标。"),
            "5": ("✓", "候选人资格能力条件、无效投标判定和部分业绩公开。"),
            "6": ("✓", "公开所有有效投标人的商务、技术、报价、其他和最终总分。"),
            "7": ("✓", "建设范围为南京地铁5号线新线食堂智能结算设备，交货期明确。"),
            "8": ("✓", "前三名候选公司、报价和排名完整披露。"),
            "9": ("✓", "可由最终总分最高、价格分和业绩说明解释中标原因。"),
        },
    },
    {
        "name": "中信银行杭州分行智慧食堂软硬件服务商集采入围项目",
        "got": 6,
        "partial": 3,
        "missing": 0,
        "summary": "这个项目一共要抓 9 个，现在确认抓到 6 个，另外 3 个部分抓到；没有完全空缺项，主要缺评分细则、总分和软件模块级参数。",
        "file": "docs/deliverables/20260615-full-candidate-tender-details/02-中信银行杭州分行智慧食堂软硬件服务商集采入围项目.xlsx",
        "items": {
            "1": ("✓", "项目编号、预算、服务期、入围数量、工作内容可确认。"),
            "2": ("✓", "16类智慧食堂软硬件/耗材单价完整披露。"),
            "3": ("△", "招标公告披露软硬件服务范围，未披露模块级软件参数。"),
            "4": ("✓", "人脸终端、称重计量一体机、绑盘机、智慧餐台、速通门等硬件价格披露。"),
            "5": ("✓", "投标人资格要求公开。"),
            "6": ("△", "候选排序和单价公开，但评分细则/总分未公开。"),
            "7": ("✓", "服务范围为银行客户智慧食堂综合服务，服务期2年。"),
            "8": ("✓", "前五名候选公司披露，前三名可完整列出。"),
            "9": ("△", "可按候选排序和报价分析，但缺评标报告无法完整解释原因。"),
        },
    },
    {
        "name": "中国农业银行广东省分行智慧食堂场景建设设备项目",
        "got": 6,
        "partial": 3,
        "missing": 0,
        "summary": "这个项目一共要抓 9 个，现在确认抓到 6 个，另外 3 个部分抓到；没有完全空缺项，主要缺评分细则、总分和设备详细技术参数。",
        "file": "docs/deliverables/20260615-full-candidate-tender-details/03-中国农业银行广东省分行智慧食堂场景建设设备项目.xlsx",
        "items": {
            "1": ("✓", "项目名称、招标编号、预计采购金额、采购有效期和中标人数量可确认。"),
            "2": ("✓", "6类设备最高限价和权重披露。"),
            "3": ("△", "可按智慧食堂设备场景拆解软件能力，公开页未披露软件模块参数。"),
            "4": ("✓", "高配/基础/低配设备、空白卡的最高限价和权重披露。"),
            "5": ("✓", "投标人资格和禁入/信用/关联/联合体限制披露。"),
            "6": ("△", "候选排序和投标单价公开，但评分细则/总分未公开。"),
            "7": ("✓", "采购范围为广东省分行智慧食堂场景建设设备及相关服务，有效期明确。"),
            "8": ("✓", "前六名候选公司披露，前三名可完整列出。"),
            "9": ("△", "可按候选排序和单价分析，缺评标报告无法完整解释原因。"),
        },
    },
]

DEEP_DIVE_ROWS = [
    [
        "南京地铁5号线工程新线食堂智能结算设备采购",
        "新增：招标公告原文要点、南京得分逐项校验、南京报价与排名对应、南京技术标0分明细、南京候选人业绩明细、商务分反推说明、报价分公式追踪、报价分反推计算、供应商公开资质证书、需登录补齐清单、得分解释",
        "最终总得分=商务+技术+投标报价+其他；南京小牛7.00+0.00+42.03+45.46=94.49。商务分可按公开评分业绩数量反推：南京小牛4项评分业绩=7分，江苏移动1项评分业绩=4分，浙江云澎4项评分业绩=7分；该反推需招标文件确认。",
        "浙江云澎前三名中报价最低220.811000万元，但报价分35.42、总分84.94。按报价分反推，价格满分很可能为45分，评标基准价约290.35万-291.12万元，高于基准价每1%约扣0.6分，低于基准价每1%约扣0.4分；云澎低于基准价约23.95%，扣9.58分，45-9.58=35.42。",
        "技术标公开明细三项评审因素均显示7名评委0.00；公开页未拆出“其他”45.46的内部构成。供应商资质证书已先抓公开资料，证书编号/有效期需天眼查或企业信用平台登录补齐。",
    ],
    [
        "中信银行杭州分行智慧食堂软硬件服务商集采入围项目",
        "新增：设备单价逐项对比、候选公司价格画像、得分解释",
        "候选公示未披露商务分、技术分、报价分或总分，只披露五家候选排序和16类设备单价。",
        "常州勤网在多项设备上最低或并列最低；表内已逐项标出最低价、最低供应商、最高价和价差。",
        "16项单价简单合计只是非官方价格画像，不等于官方评标价；如需官方得分需招标文件/评标报告。",
    ],
    [
        "中国农业银行广东省分行智慧食堂场景建设设备项目",
        "新增：限价权重明细、候选报价排序对应、得分解释",
        "候选公示未披露总分，只披露第一至第六候选人及投标单价；招标公告披露6类设备最高限价和权重。",
        "广电运通2105.30元最低且排名第一；但海康威视2848.70元低于第三、第四候选人的报价却排第五，说明候选排序不按价格单项排序。",
        "价格权重可解释采购价格结构，但不能还原技术/商务得分；需农银e采平台招标文件或评标报告补齐。",
    ],
]


def style(cell, fill: str | None = None, bold: bool = False, color: str = "1F1F1F") -> None:
    cell.font = Font(name=FONT, size=10, bold=bold, color=color)
    cell.alignment = Alignment(wrap_text=True, vertical="top")
    cell.border = BORDER
    if fill:
        cell.fill = PatternFill("solid", fgColor=fill)


def title(ws, text: str, cols: int) -> None:
    ws.merge_cells(start_row=1, start_column=1, end_row=1, end_column=cols)
    cell = ws.cell(1, 1, text)
    cell.font = Font(name=FONT, size=15, bold=True, color=WHITE)
    cell.fill = PatternFill("solid", fgColor=BLUE)
    cell.alignment = Alignment(horizontal="center", vertical="center")


def write_table(ws, start_row: int, headers: list[str], rows: list[list[str]]) -> int:
    for c, header in enumerate(headers, 1):
        cell = ws.cell(start_row, c, header)
        style(cell, LIGHT_BLUE, True, "14344A")
        cell.alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)
    r = start_row
    for row in rows:
        r += 1
        for c, value in enumerate(row, 1):
            fill = None
            if value == "✓":
                fill = GREEN
            elif value == "△":
                fill = YELLOW
            elif value == "✗":
                fill = RED
            cell = ws.cell(r, c, value)
            style(cell, fill)
    ws.auto_filter.ref = f"A{start_row}:{get_column_letter(len(headers))}{r}"
    return r + 2


def widths(ws, values: list[int]) -> None:
    for i, width in enumerate(values, 1):
        ws.column_dimensions[get_column_letter(i)].width = width
    for r in range(1, ws.max_row + 1):
        ws.row_dimensions[r].height = 42
    ws.freeze_panes = "A3"


def build() -> None:
    wb = Workbook()
    wb.remove(wb.active)

    ws = wb.create_sheet("模板九项定义")
    title(ws, "项目级招投标详细抓取模板九项定义", 4)
    write_table(
        ws,
        3,
        ["序号", "模板项", "抓取内容", "模板依据"],
        [[n, item, desc, str(TEMPLATE)] for n, item, desc in TEMPLATE_ITEMS],
    )
    widths(ws, [10, 28, 92, 72])

    ws = wb.create_sheet("原3项目覆盖率")
    title(ws, "原 3 个项目按九项模板抓取覆盖率", 13)
    headers = ["项目", "抓到数", "缺口数", "一句话结论"] + [f"{n}.{item}" for n, item, _ in TEMPLATE_ITEMS] + ["来源"]
    rows = []
    for project in ORIGINAL_PROJECTS:
        row = [project["name"], str(project["count"]), str(9 - project["count"]), project["summary"]]
        for n, _, _ in TEMPLATE_ITEMS:
            row.append(project["items"][n][0])
        row.append(project["source"])
        rows.append(row)
    write_table(ws, 3, headers, rows)
    widths(ws, [42, 10, 10, 70] + [18] * 9 + [58])

    ws = wb.create_sheet("逐项缺口说明")
    title(ws, "原 3 个项目逐项缺口说明", 5)
    rows = []
    item_map = {n: item for n, item, _ in TEMPLATE_ITEMS}
    for project in ORIGINAL_PROJECTS:
        for n, _, _ in TEMPLATE_ITEMS:
            status, note = project["items"][n]
            rows.append([project["name"], n, item_map[n], status, note])
    write_table(ws, 3, ["项目", "序号", "模板项", "状态", "说明"], rows)
    widths(ws, [42, 8, 28, 10, 90])

    ws = wb.create_sheet("可抓全项目候选")
    title(ws, "可用于全量样例的 3 个项目候选", 7)
    write_table(
        ws,
        3,
        ["项目", "为什么适合全量抓取", "覆盖判断", "前三/主要公司", "关键数据", "来源", "下一步"],
        [[c["name"], c["why"], c["coverage"], c["companies"], c["key_data"], c["sources"], c["next"]] for c in FULL_CANDIDATES],
    )
    widths(ws, [38, 64, 22, 48, 62, 82, 52])

    ws = wb.create_sheet("好抓3项目抓取结果")
    title(ws, "好抓 3 个项目模板抓取结果", 16)
    headers = ["项目", "抓到数", "部分数", "缺口数", "一句话结论", "输出文件"] + [f"{n}.{item}" for n, item, _ in TEMPLATE_ITEMS]
    rows = []
    for project in FULL_SCRAPED_PROJECTS:
        row = [
            project["name"],
            str(project["got"]),
            str(project["partial"]),
            str(project["missing"]),
            project["summary"],
            project["file"],
        ]
        for n, _, _ in TEMPLATE_ITEMS:
            row.append(project["items"][n][0])
        rows.append(row)
    write_table(ws, 3, headers, rows)
    widths(ws, [42, 10, 10, 10, 74, 78] + [18] * 9)

    ws = wb.create_sheet("好抓3项目逐项说明")
    title(ws, "好抓 3 个项目逐项说明", 5)
    item_map = {n: item for n, item, _ in TEMPLATE_ITEMS}
    rows = []
    for project in FULL_SCRAPED_PROJECTS:
        for n, _, _ in TEMPLATE_ITEMS:
            status, note = project["items"][n]
            rows.append([project["name"], n, item_map[n], status, note])
    write_table(ws, 3, ["项目", "序号", "模板项", "状态", "说明"], rows)
    widths(ws, [42, 8, 28, 10, 92])

    ws = wb.create_sheet("本轮深挖得分说明")
    title(ws, "本轮深挖得分与价格对应说明", 5)
    write_table(
        ws,
        3,
        ["项目", "本轮新增Sheet", "得分解释", "价格/排名对应", "仍需补齐"],
        DEEP_DIVE_ROWS,
    )
    widths(ws, [42, 72, 82, 86, 72])

    ws = wb.create_sheet("总论")
    title(ws, "总论", 2)
    summary_rows = [
        ["模板固化", f"已将用户提供模板复制到项目内：{TEMPLATE}"],
        ["原三项目总覆盖", "三项目合计应抓 27 项，严格按项目自身公开/本机来源确认，目前抓到 8 项，缺 19 项。即：单项目模板 9 项；三个项目合计抓到 8 项；缺口 19 项。"],
        ["延庆结论", ORIGINAL_PROJECTS[0]["summary"]],
        ["昌平结论", ORIGINAL_PROJECTS[1]["summary"]],
        ["海淀结论", ORIGINAL_PROJECTS[2]["summary"]],
        ["好抓三项目总覆盖", "三个好抓项目合计应抓 27 项，目前确认抓到 18 项，部分抓到 9 项，完全空缺 0 项。"],
        ["全量候选结论", "已抓取 3 个更适合做全量样例的项目：南京地铁5号线食堂智能结算设备、中信银行杭州分行智慧食堂软硬件集采、农行广东省分行智慧食堂设备。南京地铁最接近全量；中信和农行主要缺评分细则/评标报告。"],
        ["本轮深挖结论", "已在3个好抓项目Excel中新增得分解释/价格对应类sheet，并在本总论表新增“本轮深挖得分说明”。南京项目可解释到总分公式；中信、农行项目因公开页未披露总分，只能解释候选排序与报价/限价的对应关系。"],
    ]
    write_table(ws, 3, ["事项", "结论"], summary_rows)
    widths(ws, [28, 120])

    OUTPUT.parent.mkdir(parents=True, exist_ok=True)
    wb.save(OUTPUT)
    print(OUTPUT)


if __name__ == "__main__":
    build()
