#!/usr/bin/env python3
"""Build the one-page customer explanation from the retained Kangbite template."""

from __future__ import annotations

import argparse
import shutil
import subprocess
from pathlib import Path

from docx import Document
from docx.enum.table import WD_CELL_VERTICAL_ALIGNMENT
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
from docx.shared import Cm, Pt, RGBColor


ROOT = Path(__file__).resolve().parents[3]
SKILL_DIR = ROOT / "standards-stack/agent-skills/skills/kangbite-word-template"
TEMPLATE = SKILL_DIR / "assets/kangbite-digital-sports-word-template.docx"
PREPARE = SKILL_DIR / "scripts/prepare_working_copy.py"
TEMPLATE_SPEC = SKILL_DIR / "references/template-spec.md"

ORANGE = "F28C28"
DARK = "1F2937"
MUTED = "667085"
LIGHT_ORANGE = "FFF5E8"


def set_cell_shading(cell, fill: str) -> None:
    tc_pr = cell._tc.get_or_add_tcPr()
    shading = tc_pr.find(qn("w:shd"))
    if shading is None:
        shading = OxmlElement("w:shd")
        tc_pr.append(shading)
    shading.set(qn("w:fill"), fill)
    shading.set(qn("w:val"), "clear")


def set_cell_margins(cell, top=120, start=180, bottom=120, end=180) -> None:
    tc_pr = cell._tc.get_or_add_tcPr()
    tc_mar = tc_pr.first_child_found_in("w:tcMar")
    if tc_mar is None:
        tc_mar = OxmlElement("w:tcMar")
        tc_pr.append(tc_mar)
    for margin, value in (("top", top), ("start", start), ("bottom", bottom), ("end", end)):
        node = tc_mar.find(qn(f"w:{margin}"))
        if node is None:
            node = OxmlElement(f"w:{margin}")
            tc_mar.append(node)
        node.set(qn("w:w"), str(value))
        node.set(qn("w:type"), "dxa")


def remove_table_borders(table) -> None:
    tbl_pr = table._tbl.tblPr
    borders = tbl_pr.first_child_found_in("w:tblBorders")
    if borders is None:
        borders = OxmlElement("w:tblBorders")
        tbl_pr.append(borders)
    for edge in ("top", "left", "bottom", "right", "insideH", "insideV"):
        tag = borders.find(qn(f"w:{edge}"))
        if tag is None:
            tag = OxmlElement(f"w:{edge}")
            borders.append(tag)
        tag.set(qn("w:val"), "nil")


def set_run_font(run, size: float, bold: bool = False, color: str = DARK) -> None:
    run.font.name = "微软雅黑"
    run._element.get_or_add_rPr().get_or_add_rFonts().set(qn("w:eastAsia"), "微软雅黑")
    run.font.size = Pt(size)
    run.font.bold = bold
    run.font.color.rgb = RGBColor.from_string(color)


def add_body_paragraph(doc, text: str, *, after=5.5, line=1.18):
    paragraph = doc.add_paragraph()
    paragraph.paragraph_format.space_after = Pt(after)
    paragraph.paragraph_format.line_spacing = line
    run = paragraph.add_run(text)
    set_run_font(run, 10.5)
    return paragraph


def add_section_heading(doc, number: str, title: str) -> None:
    paragraph = doc.add_paragraph()
    paragraph.paragraph_format.space_before = Pt(5)
    paragraph.paragraph_format.space_after = Pt(3)
    run = paragraph.add_run(f"{number}  {title}")
    set_run_font(run, 12, bold=True, color=ORANGE)


def add_timeline_row(table, date_text: str, action: str) -> None:
    cells = table.add_row().cells
    cells[0].vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
    cells[1].vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
    for cell in cells:
        set_cell_margins(cell, top=55, start=80, bottom=55, end=80)
    p0 = cells[0].paragraphs[0]
    p0.paragraph_format.space_after = Pt(0)
    r0 = p0.add_run(date_text)
    set_run_font(r0, 9.5, bold=True, color=ORANGE)
    p1 = cells[1].paragraphs[0]
    p1.paragraph_format.space_after = Pt(0)
    p1.paragraph_format.line_spacing = 1.08
    r1 = p1.add_run(action)
    set_run_font(r1, 9.5)


def build(output: Path, workdir: Path) -> None:
    workdir.mkdir(parents=True, exist_ok=True)
    shutil.copy2(TEMPLATE_SPEC, workdir / "artifact.md")
    starter = workdir / "kangbite-starter.docx"
    subprocess.run(["python3", str(PREPARE), str(TEMPLATE), str(starter)], check=True)

    doc = Document(starter)
    section = doc.sections[0]
    section.top_margin = Cm(2.54)
    section.bottom_margin = Cm(2.20)
    section.left_margin = Cm(3.175)
    section.right_margin = Cm(3.175)

    body = doc._element.body
    for paragraph in list(doc.paragraphs):
        body.remove(paragraph._element)

    normal = doc.styles["Normal"]
    normal.font.name = "微软雅黑"
    normal._element.get_or_add_rPr().get_or_add_rFonts().set(qn("w:eastAsia"), "微软雅黑")
    normal.font.size = Pt(10.5)

    title = doc.add_paragraph()
    title.alignment = WD_ALIGN_PARAGRAPH.CENTER
    title.paragraph_format.space_before = Pt(8)
    title.paragraph_format.space_after = Pt(2)
    set_run_font(title.add_run("金斯瑞项目消费订单导出金额问题说明"), 19, bold=True)

    subtitle = doc.add_paragraph()
    subtitle.alignment = WD_ALIGN_PARAGRAPH.CENTER
    subtitle.paragraph_format.space_after = Pt(10)
    set_run_font(subtitle.add_run("关于列表实收金额与导出实付金额不一致的情况说明"), 9.5, color=MUTED)

    callout = doc.add_table(rows=1, cols=1)
    callout.autofit = False
    callout.columns[0].width = Cm(14.2)
    remove_table_borders(callout)
    cell = callout.cell(0, 0)
    set_cell_shading(cell, LIGHT_ORANGE)
    set_cell_margins(cell, top=150, start=220, bottom=150, end=220)
    p = cell.paragraphs[0]
    p.paragraph_format.space_after = Pt(0)
    p.paragraph_format.line_spacing = 1.15
    set_run_font(
        p.add_run(
            "经核查，本次金额差异是我方系统导出统计口径处理不严谨造成的。"
            "7 笔已取消且未付款的订单被误计入“实付金额”，使导出合计多出 152.80 元。"
            "该问题只影响导出统计展示，未产生客户账户重复扣款或资金损失。"
            "此问题属于我方系统问题，我方承担整改责任。"
        ),
        10.5,
        bold=True,
    )

    add_section_heading(doc, "一", "问题情况")
    add_body_paragraph(
        doc,
        "在相同查询条件下，页面显示实收金额 105,706.90 元，原导出文件显示实付金额 105,859.70 元。"
        "差额 152.80 元来自 7 笔已取消且未付款的订单。",
    )

    add_section_heading(doc, "二", "整改安排")
    timeline = doc.add_table(rows=0, cols=2)
    timeline.autofit = False
    timeline.columns[0].width = Cm(3.25)
    timeline.columns[1].width = Cm(10.95)
    remove_table_borders(timeline)
    add_timeline_row(timeline, "8 月 7 日 18:00 前", "完成导出统计逻辑修复和内部测试，取消、待付款订单不再计入实付金额。")
    add_timeline_row(timeline, "8 月 8 日", "完成测试环境复核；经双方确认上线窗口后发布至生产环境。")
    add_timeline_row(timeline, "上线后 2 小时内", "按本次相同条件复核页面与导出结果，并提供口径修正版导出文件。")

    add_section_heading(doc, "三", "后续预防措施")
    add_body_paragraph(
        doc,
        "我方将统一列表和导出的金额计算规则，增加取消、待付款、已付款及退款等状态的专项测试，"
        "并把“页面与导出金额一致”纳入发布检查。修复上线前，如需使用相关导出数据，请联系我方复核并提供修正版，"
        "避免继续使用旧文件中的实付合计。",
        after=7,
    )

    closing = doc.add_paragraph()
    closing.paragraph_format.space_after = Pt(10)
    set_run_font(closing.add_run("由此给贵方带来的不便，敬请谅解。"), 10.5)

    signature = doc.add_paragraph()
    signature.alignment = WD_ALIGN_PARAGRAPH.RIGHT
    signature.paragraph_format.space_after = Pt(0)
    signature.paragraph_format.line_spacing = 1.12
    for index, line in enumerate(
        ("北京康比特体育科技股份有限公司", "数字体育科技事业部  数字技术中心", "2026 年 8 月 6 日")
    ):
        if index:
            signature.add_run().add_break()
        set_run_font(signature.add_run(line), 9.5, bold=index == 0, color=MUTED)

    output.parent.mkdir(parents=True, exist_ok=True)
    doc.save(output)


def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument("--output", type=Path, required=True)
    parser.add_argument("--workdir", type=Path, required=True)
    args = parser.parse_args()
    build(args.output.resolve(), args.workdir.resolve())
    print(f"Built: {args.output.resolve()}")


if __name__ == "__main__":
    main()
