"""Заполняет интерактивную PDF-форму, сохраняя AcroForm и создавая appearance-потоки."""

from pypdf import PdfReader, PdfWriter
from pypdf.generic import (
    ArrayObject,
    DecodedStreamObject,
    DictionaryObject,
    NameObject,
    NumberObject,
    TextStringObject,
)

SRC = "маршруты/офисный-вход/учебная-форма.pdf"
OUT = "результаты/офисный-вход/учебная-форма-заполненная.pdf"
VALUES = {
    "report_title": "Weekly report",
    "start_date": "15 October",
    "change_count": "3",
}
COLOR = "0.094118 0.141176 0.227451"
FONT_SIZE = 12


def pdf_escape(text: str) -> str:
    return text.replace("\\", r"\\").replace("(", r"\(").replace(")", r"\)")


def build_appearance(writer, value: str, width: float, height: float, font):
    stream = DecodedStreamObject()
    content = (
        f"q BT /Helv {FONT_SIZE} Tf {COLOR} rg "
        f"2 {height / 2 - FONT_SIZE / 2 - 1:.2f} Td ({pdf_escape(value)}) Tj ET Q"
    )
    stream.set_data(content.encode("latin-1"))
    stream[NameObject("/Type")] = NameObject("/XObject")
    stream[NameObject("/Subtype")] = NameObject("/Form")
    stream[NameObject("/FormType")] = NumberObject(1)
    stream[NameObject("/BBox")] = ArrayObject(
        [NumberObject(0), NumberObject(0), NumberObject(round(width)), NumberObject(round(height))]
    )
    resources = DictionaryObject()
    fonts = DictionaryObject()
    fonts[NameObject("/Helv")] = font
    resources[NameObject("/Font")] = fonts
    stream[NameObject("/Resources")] = resources
    return writer._add_object(stream)


reader = PdfReader(SRC)
writer = PdfWriter(clone_from=reader)

acroform = writer._root_object["/AcroForm"]
helv = acroform["/DR"]["/Font"]["/Helv"]

filled = []
for field_ref in acroform["/Fields"]:
    field = field_ref.get_object()
    name = str(field.get("/T"))
    if name not in VALUES:
        continue
    value = VALUES[name]
    field[NameObject("/V")] = TextStringObject(value)
    widgets = (
        [field]
        if field.get("/Subtype") == "/Widget"
        else [kid.get_object() for kid in field.get("/Kids", [])]
    )
    for widget in widgets:
        widget[NameObject("/V")] = TextStringObject(value)
        x0, y0, x1, y1 = (float(v) for v in widget["/Rect"])
        ap = DictionaryObject()
        ap[NameObject("/N")] = build_appearance(writer, value, x1 - x0, y1 - y0, helv)
        widget[NameObject("/AP")] = ap
        filled.append((name, value))

with open(OUT, "wb") as handle:
    writer.write(handle)

print("filled:", filled)
