# -*- coding: utf-8 -*-
"""Generate 客户分级与黑名单规则.docx with tables and basic typography."""
from pathlib import Path

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


def set_cell_shading(cell, fill: str) -> None:
    """fill: hex without # e.g. EAEAEA"""
    tc = cell._tc
    tcPr = tc.get_or_add_tcPr()
    shd = OxmlElement("w:shd")
    shd.set(qn("w:fill"), fill)
    shd.set(qn("w:val"), "clear")
    tcPr.append(shd)


def set_table_borders(table) -> None:
    tbl = table._tbl
    tblPr = tbl.tblPr
    if tblPr is None:
        tblPr = OxmlElement("w:tblPr")
        tbl.insert(0, tblPr)
    borders = OxmlElement("w:tblBorders")
    for edge in ("top", "left", "bottom", "right", "insideH", "insideV"):
        el = OxmlElement(f"w:{edge}")
        el.set(qn("w:val"), "single")
        el.set(qn("w:sz"), "4")
        el.set(qn("w:space"), "0")
        el.set(qn("w:color"), "333333")
        borders.append(el)
    tblPr.append(borders)


def add_heading_doc(doc, text: str, level: int) -> None:
    p = doc.add_heading(text, level=level)
    for run in p.runs:
        run.font.name = "PingFang SC"
        run._element.rPr.rFonts.set(qn("w:eastAsia"), "PingFang SC")


def add_para(doc, text: str, bold: bool = False) -> None:
    p = doc.add_paragraph()
    run = p.add_run(text)
    run.font.name = "PingFang SC"
    run._element.rPr.rFonts.set(qn("w:eastAsia"), "PingFang SC")
    run.font.size = Pt(10.5)
    if bold:
        run.bold = True


def add_bullet_list(doc, items: list) -> None:
    for t in items:
        p = doc.add_paragraph(style="List Bullet")
        run = p.add_run(t)
        run.font.name = "PingFang SC"
        run._element.rPr.rFonts.set(qn("w:eastAsia"), "PingFang SC")
        run.font.size = Pt(10.5)


def add_table(doc, headers: list, rows: list, header_fill: str = "EAEAEA") -> None:
    table = doc.add_table(rows=1 + len(rows), cols=len(headers))
    table.style = "Table Grid"
    set_table_borders(table)
    hdr_cells = table.rows[0].cells
    for i, h in enumerate(headers):
        hdr_cells[i].text = h
        set_cell_shading(hdr_cells[i], header_fill)
        for p in hdr_cells[i].paragraphs:
            p.alignment = WD_ALIGN_PARAGRAPH.LEFT
            for r in p.runs:
                r.bold = True
                r.font.size = Pt(9.5)
                r.font.name = "PingFang SC"
                r._element.rPr.rFonts.set(qn("w:eastAsia"), "PingFang SC")
    for ri, row in enumerate(rows):
        cells = table.rows[ri + 1].cells
        for ci, val in enumerate(row):
            cells[ci].text = str(val)
            for p in cells[ci].paragraphs:
                for r in p.runs:
                    r.font.size = Pt(9.5)
                    r.font.name = "PingFang SC"
                    r._element.rPr.rFonts.set(qn("w:eastAsia"), "PingFang SC")
    doc.add_paragraph()


def main() -> None:
    out = Path.home() / "Desktop" / "客户分级与黑名单规则.docx"
    doc = Document()
    section = doc.sections[0]
    section.page_height = Inches(11.69)
    section.page_width = Inches(8.27)
    section.left_margin = Inches(0.75)
    section.right_margin = Inches(0.75)
    section.top_margin = Inches(0.85)
    section.bottom_margin = Inches(0.85)

    t = doc.add_paragraph()
    t.alignment = WD_ALIGN_PARAGRAPH.CENTER
    r = t.add_run("客户分级（ABC）、风险标签与黑名单规则")
    r.bold = True
    r.font.size = Pt(17)
    r.font.name = "PingFang SC"
    r._element.rPr.rFonts.set(qn("w:eastAsia"), "PingFang SC")

    st = doc.add_paragraph()
    st.alignment = WD_ALIGN_PARAGRAPH.CENTER
    rr = st.add_run("版本：草案 · 适用于 ToB 合同、收款与开票场景（可按业务微调阈值）")
    rr.font.size = Pt(9.5)
    rr.font.color.rgb = RGBColor(0x55, 0x55, 0x55)
    rr.font.name = "PingFang SC"
    rr._element.rPr.rFonts.set(qn("w:eastAsia"), "PingFang SC")

    doc.add_paragraph()

    add_heading_doc(doc, "一、客户分级（ABC）", level=1)
    add_heading_doc(doc, "1. 分级目的", level=2)
    add_bullet_list(
        doc,
        [
            "资源投入：授信、账期、折扣、专属服务与响应时效。",
            "风控：A 类可放宽流程，C 类收紧合同与收款条款。",
            "统计：报表、提成、续约策略分层。",
        ],
    )

    add_heading_doc(doc, "2. 维度与计分（建议每年或每季复核）", level=2)
    add_table(
        doc,
        ["维度", "说明", "权重示例"],
        [
            ["贡献度", "近 12 个月含税回款、毛利、合同金额", "35%"],
            ["履约与回款", "逾期次数、最长逾期天数、DSO", "25%"],
            ["合作稳定性", "合作月数、续约、纠纷/索赔次数", "20%"],
            ["战略价值", "品牌、标杆案例、增量潜力、独家合作", "20%"],
        ],
    )
    add_para(doc, "可将各维度标准化为 0–100 分，加权得综合分，再划档；或直接按「硬性门槛 + 一票否决」定级。")

    add_heading_doc(doc, "3. 等级定义与标准（示例）", level=2)
    add_table(
        doc,
        ["等级", "综合分（示例）", "典型特征"],
        [
            ["A", "≥ 80", "回款好、贡献高或战略客户；近 12 个月无严重逾期、无未结重大纠纷"],
            ["B", "50–79", "正常合作；偶有短逾期已结清；贡献中等"],
            ["C", "< 50", "新客观察期、小额长尾、或回款/纠纷问题较多"],
        ],
    )

    add_heading_doc(doc, "4. 硬性调整（建议写死规则）", level=2)
    add_bullet_list(
        doc,
        [
            "近 12 个月出现单次逾期 > 60 天或累计逾期 ≥ 3 次：最高不超过 B。",
            "存在未结法律诉讼或重大合规调查：暂定为 C，直至结案。",
            "新签约 90 天内且无足够交易数据：默认 C 或 B（观察），标签单独标「新客观察」。",
        ],
    )

    add_heading_doc(doc, "5. 分级权益与约束（示例）", level=2)
    add_table(
        doc,
        ["项目", "A", "B", "C"],
        [
            ["标准账期", "可按合同约定略优", "标准", "缩短或预付比例提高"],
            ["授信额度", "可申请较高额度", "中等", "低或零，款到发货"],
            ["价格/折扣", "可申请专项政策", "标准政策", "原则上无额外折扣"],
            ["合同审批", "可简化部分条款", "标准", "法务/财务加签"],
            ["服务响应", "优先 SLA", "标准", "标准（不承诺加急）"],
        ],
    )

    add_heading_doc(doc, "二、风险标签", level=1)
    add_heading_doc(doc, "1. 设计原则", level=2)
    add_bullet_list(
        doc,
        [
            "标签≠等级：同一客户可有多个标签；黑名单与部分标签可联动自动拦截。",
            "来源：系统规则自动打标 + 人工标注；重要标签变更留痕。",
            "有效期：部分标签可设过期时间（如「短期资金链紧张」6 个月复核）。",
        ],
    )
    add_para(doc, "建议字段：标签代码、名称、级别、来源、备注、生效时间。")

    add_heading_doc(doc, "2. 信用与回款", level=2)
    add_table(
        doc,
        ["标签代码", "名称", "级别", "典型触发"],
        [
            ["CR-01", "逾期预警", "中", "当前存在逾期或近 6 个月有逾期"],
            ["CR-02", "严重拖欠", "高", "逾期 > 30 天未结或历史坏账记录"],
            ["CR-03", "频繁改账期", "低", "一年内申请延长账期 ≥ 3 次"],
        ],
    )

    add_heading_doc(doc, "3. 合规与法律", level=2)
    add_table(
        doc,
        ["标签代码", "名称", "级别", "典型触发"],
        [
            ["CP-01", "资质存疑", "中", "证照过期、抬头与付款主体不一致"],
            ["CP-02", "涉诉/仲裁", "高", "与我方或第三方重大未结诉讼"],
            ["CP-03", "制裁/高风险地区", "高", "名单筛查命中（按公司合规清单）"],
        ],
    )

    add_heading_doc(doc, "4. 经营与履约", level=2)
    add_table(
        doc,
        ["标签代码", "名称", "级别", "典型触发"],
        [
            ["OP-01", "频繁争议", "中", "合同争议、扣款争议次数超阈值"],
            ["OP-02", "车辆/资产高风险", "中–高", "违章、事故、骗保嫌疑等业务规则（按公司业务定义）"],
            ["OP-03", "信息不实", "中", "虚假联系人、空头公司等核实结果"],
        ],
    )

    add_heading_doc(doc, "5. 操作与流程", level=2)
    add_table(
        doc,
        ["标签代码", "名称", "级别", "典型触发"],
        [
            ["PR-01", "开票异常", "低", "频繁退票、抬头变更异常"],
            ["PR-02", "多头签约", "低", "同一实控人多主体分散签约"],
        ],
    )
    add_para(doc, "级别建议：低 / 中 / 高 / 致命（致命仅建议与黑名单联动）。", bold=True)

    add_heading_doc(doc, "6. 标签与系统行为（示例）", level=2)
    add_table(
        doc,
        ["级别", "建议动作"],
        [
            ["低", "仅展示与报表，不拦截"],
            ["中", "合同/大额订单增加审批节点；降低默认授信"],
            ["高", "禁止新增授信；新合同须法务/财务双签；可限制开票额度"],
            ["致命", "与黑名单规则对齐，禁止新业务或仅允许收尾"],
        ],
    )

    add_heading_doc(doc, "三、黑名单规则", level=1)
    add_heading_doc(doc, "1. 黑名单分级（建议）", level=2)
    add_table(
        doc,
        ["级别", "名称", "含义"],
        [
            ["L1", "观察名单", "重点监控，限制部分权限"],
            ["L2", "业务冻结", "禁止新签合同、新增订单/车辆，允许履约收尾与收款"],
            ["L3", "全面禁止", "禁止新业务；按法务意见处理尾款与争议"],
        ],
    )

    add_heading_doc(doc, "2. 进入条件（由风控委员会或授权人最终裁定）", level=2)
    add_para(doc, "进入 L2（业务冻结）——示例：", bold=True)
    add_bullet_list(
        doc,
        [
            "恶意拖欠：应付账款逾期 > 90 天且经书面催收无效。",
            "欺诈或伪造：伪造资质、虚构交易、骗取发票或补贴等查实。",
            "重大违约：单方毁约造成损失达约定金额或内部红线。",
            "司法：被列为失信被执行人，或对我方提起恶意诉讼并造成实质风险。",
            "合规：命中内外部黑名单库、制裁名单且公司政策要求停止合作。",
        ],
    )
    add_para(doc, "进入 L3（全面禁止）——示例：", bold=True)
    add_bullet_list(
        doc,
        [
            "L2 情形加重且法务/高管批准。",
            "刑事立案或监管机构明确要求终止合作。",
        ],
    )
    add_para(doc, "进入 L1（观察名单）——示例：", bold=True)
    add_bullet_list(
        doc,
        [
            "连续 2 次逾期 > 15 天。",
            "存在未结争议金额超过阈值。",
            "高风险标签（如 CP-02、CR-02）未解除超过 90 天。",
        ],
    )

    add_heading_doc(doc, "3. 系统与业务规则（落地）", level=2)
    add_bullet_list(
        doc,
        [
            "客户主数据：标记黑名单级别、原因代码、生效日、操作人、附件（催收记录、判决书等）。",
            "合同：L2/L3 禁止新建合同；进行中合同可走「例外审批」仅允许极少数变更（如收款账户）。",
            "订单/开票：L1 可设单笔限额；L2/L3 禁止新开票或仅允许红冲/收尾类单据（按税务合规）。",
            "消息：销售、运营界面显著提示，避免误接单。",
        ],
    )

    add_heading_doc(doc, "4. 移出与复议", level=2)
    add_bullet_list(
        doc,
        [
            "L1：满足连续 6 个月无新增逾期、争议结案，由销售发起，财务复核后可移除。",
            "L2/L3：须还清欠款或达成书面和解 + 法务/风控签字；L3 须高管或委员会批准。",
            "全程保留审计日志；禁止个人擅自移出。",
        ],
    )

    add_heading_doc(doc, "5. 与 ABC、标签的联动（建议）", level=2)
    add_bullet_list(
        doc,
        [
            "进入 L2/L3 → 客户等级强制为 C（或显示「黑名单-冻结」覆盖原等级）。",
            "标签 CR-02、CP-02、CP-03 在确认后自动建议进入 L1 或触发 L2 审批流。",
            "A 类客户进入黑名单须升级审批（防止误伤大客户）。",
        ],
    )

    add_heading_doc(doc, "四、模块数据模型提示（可选）", level=1)
    add_bullet_list(
        doc,
        [
            "客户表：abc_level、blacklist_level、blacklist_reason_code、blacklist_since、abc_reviewed_at。",
            "客户标签表：多对多，tag_id、source（rule/manual）、severity、expires_at。",
            "规则引擎表（可选）：规则 ID、条件 JSON、动作（打标 / 调级 / 推审批）。",
        ],
    )

    foot = doc.add_paragraph()
    rr2 = foot.add_run(
        "本文档由 ONE-OS 项目辅助生成，正式使用前请经法务、财务与业务负责人审定阈值与审批链。"
    )
    rr2.font.size = Pt(9)
    rr2.font.color.rgb = RGBColor(0x44, 0x44, 0x44)
    rr2.font.name = "PingFang SC"
    rr2._element.rPr.rFonts.set(qn("w:eastAsia"), "PingFang SC")

    doc.save(out)
    print(f"Wrote: {out}")


if __name__ == "__main__":
    main()
