#!/usr/bin/env python3
"""Build the public-facing Kangbite smart-canteen Douyin campaign proposal."""

from __future__ import annotations

import argparse
import re
from pathlib import Path

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


ORANGE = "E65C1E"
DEEP_ORANGE = "E74D1F"
INK = "101010"
NAVY = "2B3440"
GRAY = "606773"
PALE_ORANGE = "FDEFE4"
WARM_WHITE = "FDFAF7"
PALE_GREEN = "EDF7EA"
GREEN = "5A983B"


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


def set_cell_margins(cell, top=120, start=140, bottom=120, end=140) -> 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 key, value in (("top", top), ("start", start), ("bottom", bottom), ("end", end)):
        node = tc_mar.find(qn(f"w:{key}"))
        if node is None:
            node = OxmlElement(f"w:{key}")
            tc_mar.append(node)
        node.set(qn("w:w"), str(value))
        node.set(qn("w:type"), "dxa")


def set_repeat_table_header(row) -> None:
    tr_pr = row._tr.get_or_add_trPr()
    tbl_header = OxmlElement("w:tblHeader")
    tbl_header.set(qn("w:val"), "true")
    tr_pr.append(tbl_header)


def font_run(run, size=10.5, bold=False, color=INK, name="Microsoft YaHei") -> None:
    run.font.name = name
    run._element.rPr.rFonts.set(qn("w:eastAsia"), name)
    run.font.size = Pt(size)
    run.font.bold = bold
    run.font.color.rgb = RGBColor.from_string(color)


def add_inline(paragraph, text: str, size=10.5, color=INK, bold_all=False) -> None:
    parts = re.split(r"(\*\*.+?\*\*|`.+?`)", text)
    for part in parts:
        if not part:
            continue
        is_bold = part.startswith("**") and part.endswith("**")
        is_code = part.startswith("`") and part.endswith("`")
        clean = part[2:-2] if is_bold else part[1:-1] if is_code else part
        run = paragraph.add_run(clean)
        font_run(
            run,
            size=size,
            bold=bold_all or is_bold,
            color=ORANGE if is_bold else color,
            name="Menlo" if is_code else "Microsoft YaHei",
        )


def set_body_paragraph(p, after=5, before=0, line=1.35) -> None:
    fmt = p.paragraph_format
    fmt.space_before = Pt(before)
    fmt.space_after = Pt(after)
    fmt.line_spacing = line
    fmt.widow_control = True


def add_heading(doc, text: str, level: int) -> None:
    p = doc.add_paragraph()
    if level == 2:
        p.paragraph_format.page_break_before = True
        p.paragraph_format.space_after = Pt(11)
        run = p.add_run(text)
        font_run(run, size=20, bold=True, color=INK)
        p_bdr = OxmlElement("w:pBdr")
        bottom = OxmlElement("w:bottom")
        bottom.set(qn("w:val"), "single")
        bottom.set(qn("w:sz"), "16")
        bottom.set(qn("w:space"), "7")
        bottom.set(qn("w:color"), ORANGE)
        p_bdr.append(bottom)
        p._p.get_or_add_pPr().append(p_bdr)
    elif level == 3:
        p.paragraph_format.space_before = Pt(10)
        p.paragraph_format.space_after = Pt(5)
        run = p.add_run(text)
        font_run(run, size=14, bold=True, color=ORANGE)
    else:
        p.paragraph_format.space_before = Pt(6)
        p.paragraph_format.space_after = Pt(3)
        run = p.add_run(text)
        font_run(run, size=11.5, bold=True, color=NAVY)


def add_quote(doc, text: str) -> None:
    table = doc.add_table(rows=1, cols=1)
    table.alignment = WD_TABLE_ALIGNMENT.CENTER
    table.autofit = False
    cell = table.cell(0, 0)
    cell.width = Cm(15.5)
    set_cell_shading(cell, PALE_ORANGE)
    set_cell_margins(cell, top=170, start=240, bottom=170, end=240)
    p = cell.paragraphs[0]
    p.alignment = WD_ALIGN_PARAGRAPH.CENTER
    add_inline(p, text.strip(), size=12, color=DEEP_ORANGE, bold_all=True)
    set_body_paragraph(p, after=0, line=1.2)
    spacer = doc.add_paragraph()
    spacer.paragraph_format.space_after = Pt(0)


def add_markdown_table(doc, rows: list[list[str]]) -> None:
    if not rows:
        return
    cols = max(len(row) for row in rows)
    table = doc.add_table(rows=len(rows), cols=cols)
    table.alignment = WD_TABLE_ALIGNMENT.CENTER
    table.autofit = True
    table.style = "Table Grid"
    for i, row in enumerate(rows):
        for j in range(cols):
            cell = table.cell(i, j)
            cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
            set_cell_margins(cell)
            if i == 0:
                set_cell_shading(cell, ORANGE)
            elif i % 2 == 0:
                set_cell_shading(cell, WARM_WHITE)
            p = cell.paragraphs[0]
            add_inline(
                p,
                row[j] if j < len(row) else "",
                size=9,
                color="FFFFFF" if i == 0 else INK,
                bold_all=(i == 0),
            )
            set_body_paragraph(p, after=0, line=1.12)
    set_repeat_table_header(table.rows[0])


def parse_markdown(doc, path: Path) -> None:
    lines = path.read_text(encoding="utf-8").splitlines()
    table_rows: list[list[str]] = []
    skip_first_title = True

    def flush_table() -> None:
        nonlocal table_rows
        if table_rows:
            usable = [
                row
                for row in table_rows
                if not all(re.fullmatch(r"\s*:?-{3,}:?\s*", cell) for cell in row)
            ]
            add_markdown_table(doc, usable)
            table_rows = []

    for raw in lines:
        line = raw.rstrip()
        if line.startswith("|") and line.endswith("|"):
            table_rows.append([cell.strip() for cell in line.strip("|").split("|")])
            continue
        flush_table()
        if not line:
            continue
        if line.startswith("# "):
            if skip_first_title:
                skip_first_title = False
                continue
            add_heading(doc, line[2:].strip(), 2)
        elif line.startswith("## "):
            add_heading(doc, line[3:].strip(), 2)
        elif line.startswith("### "):
            add_heading(doc, line[4:].strip(), 3)
        elif line.startswith("#### "):
            add_heading(doc, line[5:].strip(), 4)
        elif line.startswith("> "):
            add_quote(doc, line[2:])
        elif re.match(r"^\d+\.\s+", line):
            p = doc.add_paragraph()
            p.paragraph_format.left_indent = Cm(0.55)
            p.paragraph_format.first_line_indent = Cm(-0.55)
            add_inline(p, line, size=10.3)
            set_body_paragraph(p, after=4)
        elif line.startswith("- "):
            p = doc.add_paragraph()
            p.paragraph_format.left_indent = Cm(0.5)
            p.paragraph_format.first_line_indent = Cm(-0.5)
            add_inline(p, "• " + line[2:], size=10.3)
            set_body_paragraph(p, after=4)
        else:
            p = doc.add_paragraph()
            add_inline(p, line, size=10.5)
            set_body_paragraph(p)
    flush_table()


def configure_styles(doc: Document) -> None:
    style = doc.styles["Normal"]
    style.font.name = "Microsoft YaHei"
    style._element.rPr.rFonts.set(qn("w:eastAsia"), "Microsoft YaHei")
    style.font.size = Pt(10.5)
    style.font.color.rgb = RGBColor.from_string(INK)
    style.paragraph_format.space_after = Pt(5)
    style.paragraph_format.line_spacing = 1.35


def add_cover(doc: Document) -> None:
    for _ in range(2):
        doc.add_paragraph()

    p = doc.add_paragraph()
    p.alignment = WD_ALIGN_PARAGRAPH.CENTER
    run = p.add_run("康比特 AI 营养智慧食堂")
    font_run(run, size=18, bold=True, color=ORANGE)
    p.paragraph_format.space_after = Pt(10)

    p = doc.add_paragraph()
    p.alignment = WD_ALIGN_PARAGRAPH.CENTER
    run = p.add_run("千人食堂焕新计划")
    font_run(run, size=30, bold=True, color=INK)
    p.paragraph_format.space_after = Pt(5)

    p = doc.add_paragraph()
    p.alignment = WD_ALIGN_PARAGRAPH.CENTER
    run = p.add_run("抖音整合营销策划案")
    font_run(run, size=17, bold=True, color=NAVY)
    p.paragraph_format.space_after = Pt(18)

    add_quote(doc, "让千人级职工食堂，吃得快、管得清、运营得好。")

    table = doc.add_table(rows=2, cols=2)
    table.alignment = WD_TABLE_ALIGNMENT.CENTER
    items = [
        ("唯一场景", "千人级职工食堂"),
        ("产品主张", "一套平台，统一结算、食安、进销存与营养健康"),
        ("活动名称", "千人食堂焕新计划"),
        ("行动入口", "预约 30 分钟千人食堂焕新诊断"),
    ]
    for index, (label, value) in enumerate(items):
        cell = table.cell(index // 2, index % 2)
        set_cell_shading(cell, PALE_ORANGE if index % 2 == 0 else PALE_GREEN)
        set_cell_margins(cell, top=180, start=180, bottom=180, end=180)
        p = cell.paragraphs[0]
        p.alignment = WD_ALIGN_PARAGRAPH.CENTER
        run = p.add_run(label + "\n")
        font_run(run, size=9.5, bold=True, color=GRAY)
        run = p.add_run(value)
        font_run(run, size=10.8, bold=True, color=INK)

    doc.add_paragraph()
    p = doc.add_paragraph()
    p.alignment = WD_ALIGN_PARAGRAPH.CENTER
    run = p.add_run("康比特数字体育科技｜2026 年 8 月")
    font_run(run, size=10.5, bold=True, color=NAVY)
    p.add_run().add_break(WD_BREAK.PAGE)


def add_footer(section) -> None:
    footer = section.footer
    p = footer.paragraphs[0]
    p.alignment = WD_ALIGN_PARAGRAPH.CENTER
    p.clear()
    run = p.add_run("康比特「千人食堂焕新计划」｜AI 营养智慧食堂")
    font_run(run, size=8, color=GRAY)


def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument("--template", required=True)
    parser.add_argument("--source", required=True)
    parser.add_argument("--output", required=True)
    args = parser.parse_args()

    doc = Document(args.template)
    configure_styles(doc)
    section = doc.sections[0]
    section.top_margin = Cm(2.54)
    section.bottom_margin = Cm(2.54)
    section.left_margin = Cm(3.175)
    section.right_margin = Cm(3.175)
    add_footer(section)
    add_cover(doc)
    parse_markdown(doc, Path(args.source))

    output = Path(args.output)
    output.parent.mkdir(parents=True, exist_ok=True)
    doc.core_properties.title = "康比特千人食堂焕新计划抖音整合营销策划案"
    doc.core_properties.subject = "千人级职工食堂｜AI 营养智慧食堂"
    doc.core_properties.author = "康比特数字体育科技"
    doc.save(output)
    print(output)


if __name__ == "__main__":
    main()
