"""WEEE 模板：按订单分类动态勾选（☐/☒）。"""
from __future__ import annotations

from pathlib import Path

from docx import Document
from docx.oxml.ns import qn
from lxml import etree

# 模板中的分类与选项（按文档顺序，德语原文作为 key）
WEEE_CATEGORIES: dict[str, list[str]] = {
    "Haushaltselektrogeräte": [
        "Wärmeübertrager",
        "Bildschirmgeräte",
        "Gasentladungslampen",
        "Lampen, außer Gasentladungslampen",
        "Großgeräte",
        "Kleine Geräte der IT&TK",
        "Kleingeräte",
    ],
    "Gewerbliche Elektrogeräte": [
        "Wärmeübertrager",
        "Bildschirmgeräte",
        "Gasentladungslampen",
        "Lampen, außer Gasentladungslampen",
        "Großgeräte",
        "Kleine Geräte der IT&TK",
        "Kleingeräte",
        "Photovoltaikmodule",
    ],
}

_CHECKED_CHAR = ""    # Wingdings 勾选 ☒
_UNCHECKED_CHAR = ""  # Wingdings 未勾选 ☐（作为编号项目符号使用）
_XML_SPACE = "{http://www.w3.org/XML/1998/namespace}space"


def _el(tag: str, children: list[etree.Element] | None = None, **attrs) -> etree.Element:
    element = etree.Element(qn(tag))
    for key, value in attrs.items():
        element.set(qn(key), value)
    for child in (children or []):
        element.append(child)
    return element


def _paragraph_text(p: etree.Element) -> str:
    return "".join(t.text or "" for t in p.iter(qn("w:t")))


def _item_label(p: etree.Element) -> str:
    text = _paragraph_text(p).strip()
    text = text.lstrip(_CHECKED_CHAR).lstrip(_UNCHECKED_CHAR).strip()
    return text


def _is_item(p: etree.Element) -> bool:
    pPr = p.find(qn("w:pPr"))
    if pPr is not None:
        numPr = pPr.find(qn("w:numPr"))
        if numPr is not None:
            numId = numPr.find(qn("w:numId"))
            if numId is not None and numId.get(qn("w:val")) == "1":
                return True
    for rf in p.iter(qn("w:rFonts")):
        if (rf.get(qn("w:ascii")) or "") == "Wingdings":
            return True
    return False


def _clear(p: etree.Element) -> None:
    for child in list(p):
        p.remove(child)


def _set_checked(p: etree.Element, label: str) -> None:
    _clear(p)

    pPr = _el("w:pPr")
    pPr.append(_el("w:pStyle", **{"w:val": "3"}))
    pPr.append(_el("w:spacing", **{"w:before": "19"}))
    pPr.append(_el("w:ind", **{"w:left": "120"}))
    p.append(pPr)

    def run(text: str, font: str | None = None, preserve: bool = False):
        r = _el("w:r")
        if font:
            rPr = _el("w:rPr")
            rPr.append(_el("w:rFonts", **{"w:ascii": font, "w:hAnsi": font}))
            r.append(rPr)
        t = _el("w:t")
        if preserve:
            t.set(_XML_SPACE, "preserve")
        t.text = text
        r.append(t)
        return r

    p.append(run(_CHECKED_CHAR, font="Wingdings"))
    p.append(run(" ", font="Times New Roman", preserve=True))
    p.append(run(label))


def _set_unchecked(p: etree.Element, label: str) -> None:
    _clear(p)

    pPr = _el("w:pPr")
    pPr.append(_el("w:pStyle", **{"w:val": "7"}))
    numPr = _el("w:numPr")
    numPr.append(_el("w:ilvl", **{"w:val": "0"}))
    numPr.append(_el("w:numId", **{"w:val": "1"}))
    pPr.append(numPr)
    tabs = _el("w:tabs")
    tabs.append(_el("w:tab", **{"w:val": "left", "w:pos": "389"}))
    pPr.append(tabs)
    pPr.append(_el("w:spacing", **{"w:before": "19", "w:after": "0", "w:line": "240", "w:lineRule": "auto"}))
    pPr.append(_el("w:ind", **{"w:left": "388", "w:right": "0", "w:hanging": "269"}))
    pPr.append(_el("w:jc", **{"w:val": "left"}))
    pPr.append(_el("w:rPr", children=[_el("w:sz", **{"w:val": "24"})]))
    p.append(pPr)

    r = _el("w:r")
    r.append(_el("w:rPr", children=[_el("w:sz", **{"w:val": "24"})]))
    t = _el("w:t")
    t.text = label
    r.append(t)
    p.append(r)


def apply_weee_categories(template_path: str | Path, output_path: str | Path, categories: dict) -> None:
    """根据订单分类，把 WEEE 模板中的分类选项改为勾选/未勾选。"""
    doc = Document(str(template_path))
    body = doc.element.body

    current_group: str | None = None
    for p in list(body.iter(qn("w:p"))):
        full = _paragraph_text(p).strip()
        if full in WEEE_CATEGORIES:
            current_group = full
            continue
        if current_group is None or not _is_item(p):
            continue

        label = _item_label(p)
        if label not in WEEE_CATEGORIES.get(current_group, []):
            continue

        selected = label in (categories.get(current_group) or [])
        if selected:
            _set_checked(p, label)
        else:
            _set_unchecked(p, label)

    output_path = Path(output_path)
    output_path.parent.mkdir(parents=True, exist_ok=True)
    doc.save(str(output_path))
