"""PDF-звіт відповідності ШТУ — ReportLab з кириличним шрифтом.

Перед першим використанням запустіть: python migrations/setup_fonts.py
"""
from __future__ import annotations

import io
from datetime import date
from pathlib import Path

from reportlab.lib import colors
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
from reportlab.lib.units import cm
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.platypus import (
    Paragraph,
    SimpleDocTemplate,
    Spacer,
    Table,
    TableStyle,
)

_FONTS_DIR = Path(__file__).parent.parent / "fonts"
_REGISTERED = False


def _register_fonts() -> None:
    global _REGISTERED
    if _REGISTERED:
        return
    regular = _FONTS_DIR / "Arial.ttf"
    bold = _FONTS_DIR / "Arial-Bold.ttf"
    if not regular.exists():
        raise FileNotFoundError(
            f"Font not found: {regular}. Run: python migrations/setup_fonts.py"
        )
    pdfmetrics.registerFont(TTFont("Arial", str(regular)))
    pdfmetrics.registerFont(TTFont("Arial-Bold", str(bold)))
    # Реєстрація родини — ReportLab автоматично вибирає bold/normal за тегом <b>
    pdfmetrics.registerFontFamily("Arial", normal="Arial", bold="Arial-Bold")
    _REGISTERED = True


def _styles() -> dict[str, ParagraphStyle]:
    base = getSampleStyleSheet()
    return {
        "title": ParagraphStyle("CyrTitle", parent=base["Title"], fontName="Arial-Bold", fontSize=14, leading=18),
        "h2": ParagraphStyle("CyrH2", parent=base["Heading2"], fontName="Arial-Bold", fontSize=12, leading=16),
        "body": ParagraphStyle("CyrBody", parent=base["Normal"], fontName="Arial", fontSize=10, leading=13),
        "small": ParagraphStyle("CyrSmall", parent=base["Normal"], fontName="Arial", fontSize=9, leading=12),
    }


def _level_label(level: int | None) -> str:
    labels = {1: "Рівень 1", 2: "Рівень 2", 3: "Рівень 3"}
    return labels.get(level, "Не сертифіковано") if level else "Не сертифіковано"


def generate_pdf(
    company: str,
    assessment_date: date,
    expert: str | None,
    certification_level: int | None,
    class_results: list[dict],
    nonconformities: list[dict],
) -> bytes:
    """Будує PDF §С.7 і повертає bytes для st.download_button."""
    _register_fonts()
    st = _styles()

    buf = io.BytesIO()
    doc = SimpleDocTemplate(
        buf,
        pagesize=A4,
        leftMargin=2 * cm, rightMargin=2 * cm,
        topMargin=2.5 * cm, bottomMargin=2 * cm,
        title=f"Звіт ШТУ — {company}",
        author=expert or "",
    )

    story = []

    # Заголовок
    story.append(Paragraph("Звіт оцінювання відповідності ШТУ", st["title"]))
    story.append(Spacer(1, 0.3 * cm))
    story.append(Paragraph(f"<b>Компанія:</b> {company}", st["body"]))
    story.append(Paragraph(f"<b>Дата оцінювання:</b> {assessment_date}", st["body"]))
    story.append(Paragraph(f"<b>Експерт:</b> {expert or '—'}", st["body"]))
    story.append(Paragraph(f"<b>Рівень сертифікації:</b> {_level_label(certification_level)}", st["body"]))
    story.append(Spacer(1, 0.5 * cm))

    # Індекси по класах
    story.append(Paragraph("Індекси відповідності по класах", st["h2"]))
    story.append(Spacer(1, 0.2 * cm))
    tbl_data = [["Клас", "Назва", "Виконано / Всього", "Індекс"]]
    for row in class_results:
        tbl_data.append([row["class"], row["name"], f"{row['met']} / {row['total']}", f"{row['index']:.1%}"])

    tbl = Table(tbl_data, colWidths=[1.5 * cm, 7 * cm, 4 * cm, 3 * cm])
    tbl.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#2c5f8a")),
        ("TEXTCOLOR", (0, 0), (-1, 0), colors.white),
        ("FONTNAME", (0, 0), (-1, 0), "Arial-Bold"),
        ("FONTNAME", (0, 1), (-1, -1), "Arial"),
        ("FONTSIZE", (0, 0), (-1, -1), 9),
        ("ROWBACKGROUNDS", (0, 1), (-1, -1), [colors.whitesmoke, colors.white]),
        ("GRID", (0, 0), (-1, -1), 0.4, colors.grey),
        ("ALIGN", (2, 0), (-1, -1), "CENTER"),
        ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
        ("TOPPADDING", (0, 0), (-1, -1), 4),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 4),
    ]))
    story.append(tbl)
    story.append(Spacer(1, 0.5 * cm))

    # Невідповідності
    story.append(Paragraph("Невідповідності", st["h2"]))
    story.append(Spacer(1, 0.2 * cm))
    if not nonconformities:
        story.append(Paragraph("Невідповідностей не виявлено.", st["body"]))
    else:
        nc_data = [["Код", "Критичність", "Термін усунення", "Рекомендація"]]
        for nc in nonconformities:
            nc_data.append([nc["code"], str(nc["severity"]), str(nc["deadline"]), nc["recommendation"]])

        nc_tbl = Table(nc_data, colWidths=[2 * cm, 2.5 * cm, 3.5 * cm, 7.5 * cm])
        nc_tbl.setStyle(TableStyle([
            ("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#8a2c2c")),
            ("TEXTCOLOR", (0, 0), (-1, 0), colors.white),
            ("FONTNAME", (0, 0), (-1, 0), "Arial-Bold"),
            ("FONTNAME", (0, 1), (-1, -1), "Arial"),
            ("FONTSIZE", (0, 0), (-1, -1), 8),
            ("ROWBACKGROUNDS", (0, 1), (-1, -1), [colors.HexColor("#fff5f5"), colors.white]),
            ("GRID", (0, 0), (-1, -1), 0.4, colors.grey),
            ("ALIGN", (1, 0), (2, -1), "CENTER"),
            ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
            ("TOPPADDING", (0, 0), (-1, -1), 3),
            ("BOTTOMPADDING", (0, 0), (-1, -1), 3),
            ("WORDWRAP", (3, 1), (3, -1), True),
        ]))
        story.append(nc_tbl)

    story.append(Spacer(1, 0.8 * cm))
    story.append(Paragraph(f"Звіт сформовано: {date.today()}", st["small"]))

    doc.build(story)
    return buf.getvalue()
