#!/usr/bin/env python3
from pathlib import Path
import re
import sys


ROOT = Path(__file__).resolve().parents[1]
PPD_DIR = ROOT / "ppd"
TEMPLATE_DIR = PPD_DIR / "_templates"
MODEL_MAP = ROOT / "supported_models.tsv"
FILTER_NAME = "pantum-4200-ps-filter"
EXPECTED_FILTER = f'*cupsFilter: "application/vnd.cups-postscript 0 {FILTER_NAME}"\n'
MANUAL_COPIES = "*cupsManualCopies: True\n"
EVEN_DUPLEX = "*cupsEvenDuplex: true\n"


def ppd_name(model: str) -> str:
    return f"Pantum {model} Series PS.ppd"


def pc_file_name(model: str) -> str:
    if len(model) <= 8:
        return f"{model}.PPD"
    return f"{model[:4]}{model[-3:]}.PPD"


def parse_models() -> list[tuple[str, str]]:
    rows = []
    for raw in MODEL_MAP.read_text(encoding="utf-8").splitlines():
        if not raw or raw.startswith("#"):
            continue
        fields = raw.split("\t")
        if len(fields) != 2:
            raise ValueError(f"bad model row: {raw!r}")
        rows.append((fields[0], fields[1]))
    return rows


def fix_jcl_ui_blocks(lines: list[str]) -> list[str]:
    fixed = []
    i = 0

    while i < len(lines):
        line = lines[i]
        match = re.match(r"^\*OpenUI\s+(\*\S+)", line)
        if not match:
            fixed.append(line)
            i += 1
            continue

        option = match.group(1).split("/", 1)[0].rstrip(":")
        block = [line]
        i += 1

        while i < len(lines):
            block.append(lines[i])
            if lines[i].startswith("*CloseUI:") and option in lines[i]:
                i += 1
                break
            i += 1

        is_jcl = any(
            item.startswith("*OrderDependency:") and f" JCLSetup {option}" in item
            for item in block
        )
        if is_jcl:
            block[0] = block[0].replace("*OpenUI", "*JCLOpenUI", 1)
            block[-1] = block[-1].replace("*CloseUI:", "*JCLCloseUI:", 1)

        fixed.extend(block)

    return fixed


def rewrite_metadata(line: str, model: str) -> str:
    replacements = {
        "*PCFileName:": f'*PCFileName: "{pc_file_name(model)}"',
        "*Product:": f'*Product: "(Pantum {model} Series)"',
        "*ShortNickName:": f'*ShortNickName: "{model} Series PS"',
        "*ModelName:": f'*ModelName: "Pantum {model} Series PS"',
        "*NickName:": f'*NickName: "Pantum {model} Series PS"',
    }

    for prefix, replacement in replacements.items():
        if line.startswith(prefix):
            return replacement + "\n"
    return line


def generate_one(model: str) -> None:
    source = TEMPLATE_DIR / ppd_name(model)
    target = PPD_DIR / ppd_name(model)

    if not source.exists():
        raise FileNotFoundError(f"missing template PPD: {source}")

    lines = source.read_text(encoding="utf-8", errors="surrogateescape").splitlines(True)
    out = []
    saw_filter = False

    for line in lines:
        if line.startswith("*cupsFilter:"):
            if not saw_filter:
                out.append(EXPECTED_FILTER)
                saw_filter = True
            continue
        if line.startswith("*cupsManualCopies:"):
            out.append(MANUAL_COPIES)
            out.append(EVEN_DUPLEX)
            continue
        if line.startswith("*cupsEvenDuplex:"):
            continue
        out.append(rewrite_metadata(line, model))

    if not saw_filter:
        raise ValueError(f"{source} does not declare a cupsFilter")

    out = fix_jcl_ui_blocks(out)
    text = "".join(out)

    checks = {
        "generated filter": EXPECTED_FILTER.strip() in text,
        "manual copies": MANUAL_COPIES.strip() in text,
        "even duplex": EVEN_DUPLEX.strip() in text,
        "model name": f'*ModelName: "Pantum {model} Series PS"' in text,
        "nickname": f'*NickName: "Pantum {model} Series PS"' in text,
        "device mdl": f"MDL:{model} series;" in text,
    }
    failed = [name for name, passed in checks.items() if not passed]
    if failed:
        raise ValueError(f"{target.name} failed checks: {', '.join(failed)}")

    target.write_text(text, encoding="utf-8", errors="surrogateescape")


def main() -> int:
    PPD_DIR.mkdir(parents=True, exist_ok=True)
    count = 0

    for model, note in parse_models():
        generate_one(model)
        print(f"{model}\t{note}")
        count += 1

    print(f"generated {count} supported PPDs")
    return 0


if __name__ == "__main__":
    try:
        raise SystemExit(main())
    except Exception as exc:
        print(f"ERROR: {exc}", file=sys.stderr)
        raise SystemExit(1)
