#!/usr/bin/env python3
"""Build docs/GRAFANA_vs_others_graphvis_pivot.pdf decision memo."""

from __future__ import annotations

from pathlib import Path

from reportlab.lib import colors
from reportlab.lib.enums import TA_LEFT
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
from reportlab.lib.units import cm
from reportlab.platypus import Paragraph, SimpleDocTemplate, Spacer, Table, TableStyle

ROOT = Path(__file__).resolve().parents[2]
OUT_PDF = ROOT / "docs" / "GRAFANA_vs_others_graphvis_pivot.pdf"
SOURCE_MD = ROOT / "docs" / "GRAFANA_vs_others_graphvis_pivot.md"


def p(text: str, style) -> Paragraph:
    return Paragraph(text.replace("\n", "<br/>"), style)


def _cell(text: str, style: ParagraphStyle) -> Paragraph:
    safe = (text or "").replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
    return Paragraph(safe.replace("\n", "<br/>"), style)


def add_table(story, headers: list[str], rows: list[list[str]], col_widths) -> None:
    styles = getSampleStyleSheet()
    head = ParagraphStyle("TblHead", parent=styles["Normal"], fontName="Helvetica-Bold", fontSize=9, leading=11)
    body = ParagraphStyle("TblBody", parent=styles["Normal"], fontSize=9, leading=11)
    data = [[_cell(h, head) for h in headers]]
    for row in rows:
        data.append([_cell(c, body) for c in row])
    t = Table(data, colWidths=col_widths)
    t.setStyle(
        TableStyle(
            [
                ("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#1565C0")),
                ("TEXTCOLOR", (0, 0), (-1, 0), colors.white),
                ("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
                ("FONTSIZE", (0, 0), (-1, -1), 9),
                ("VALIGN", (0, 0), (-1, -1), "TOP"),
                ("GRID", (0, 0), (-1, -1), 0.5, colors.lightgrey),
                ("WORDWRAP", (0, 0), (-1, -1), "CJK"),
                ("ROWBACKGROUNDS", (0, 1), (-1, -1), [colors.white, colors.HexColor("#F5F5F5")]),
                ("LEFTPADDING", (0, 0), (-1, -1), 6),
                ("RIGHTPADDING", (0, 0), (-1, -1), 6),
                ("TOPPADDING", (0, 0), (-1, -1), 4),
                ("BOTTOMPADDING", (0, 0), (-1, -1), 4),
            ]
        )
    )
    story.append(t)


def build_pdf() -> None:
    styles = getSampleStyleSheet()
    title = ParagraphStyle(
        "DocTitle",
        parent=styles["Title"],
        fontSize=18,
        spaceAfter=10,
        textColor=colors.HexColor("#1565C0"),
    )
    h1 = ParagraphStyle("H1", parent=styles["Heading1"], fontSize=14, spaceBefore=12, spaceAfter=6)
    body = ParagraphStyle("Body", parent=styles["Normal"], fontSize=10, leading=14, alignment=TA_LEFT)
    small = ParagraphStyle("Small", parent=body, fontSize=9, textColor=colors.grey)
    bullet = ParagraphStyle("Bullet", parent=body, leftIndent=14, bulletIndent=6)

    story: list = []
    story.append(p("Android Cast — Graph Visualization Pivot", title))
    story.append(p("Scope: LAMP + nginx backend, no data duplication pipeline, role-based analytics.", small))
    story.append(Spacer(1, 0.25 * cm))

    add_table(
        story,
        ["Field", "Value"],
        [
            ["Date", "2026-06-02"],
            ["Context", "apps.f0xx.org + BE Alpine (nginx + php-fpm + MariaDB)"],
            ["Constraint", "No cron ETL/data copy/pipeline complexity"],
            ["Output", "Decision memo: Grafana vs custom PHP dashboards"],
            ["Markdown source", "docs/GRAFANA_vs_others_graphvis_pivot.md"],
        ],
        [4.2 * cm, 12.2 * cm],
    )

    story.append(Spacer(1, 0.35 * cm))
    story.append(p("1. Executive summary", h1))
    story.append(
        p(
            "• Grafana is viable only if it can query MariaDB directly (or via native SQL datasource) with strict RBAC mapping and SSO/session bridging.<br/>"
            "• If direct DB + auth integration becomes complex, custom PHP dashboards are lower risk and fit your stack with zero infra additions.<br/>"
            "• Recommended path: <b>hybrid</b> — build canonical SQL views + metrics contract once; start with custom PHP pages, optionally add Grafana later reusing same SQL.",
            bullet,
        )
    )

    story.append(Spacer(1, 0.35 * cm))
    story.append(p("2. Option comparison", h1))
    add_table(
        story,
        ["Option", "Pros", "Cons / Risks", "Stack impact"],
        [
            [
                "Grafana (direct DB)",
                "Fast charting, polished visuals, alerting, flexible panels",
                "Session/RBAC integration effort; slug scoping must be enforced in queries; additional service to operate",
                "Adds Grafana service only (no ETL required)",
            ],
            [
                "Custom PHP + nginx",
                "Native app auth/session reuse; direct BE logic access; deterministic tenant filtering",
                "More frontend/dev work for visual polish; chart UX must be implemented",
                "No new runtime dependencies",
            ],
            [
                "Hybrid (recommended)",
                "Ship fast with PHP now, preserve Grafana option later; one metrics SQL contract",
                "Needs discipline in shared metrics layer",
                "Minimal immediate changes",
            ],
        ],
        [3.1 * cm, 4.4 * cm, 5.0 * cm, 3.9 * cm],
    )

    story.append(Spacer(1, 0.35 * cm))
    story.append(p("3. Role-based graph pack (suggested)", h1))
    add_table(
        story,
        ["Role", "Core dashboards", "Example charts"],
        [
            [
                "User",
                "Own slug, own devices/sessions",
                "DAU devices, avg cast duration, avg recv sessions/day, success rate, app version split",
            ],
            [
                "Slug admin",
                "All slug analytics + health",
                "Active/passive users, bandwidth send/recv 1d/7d, install source pie (Play/OTA/custom), NTP source usage and correction savings",
            ],
            [
                "Platform admin",
                "Cross-slug global + reliability",
                "Crashes per slug/device/user, trend by app version/SDK, links to ticket IDs/issues, top regressions by fingerprint",
            ],
        ],
        [2.7 * cm, 5.1 * cm, 8.6 * cm],
    )

    story.append(Spacer(1, 0.35 * cm))
    story.append(p("4. Effort and cost estimate (engineering)", h1))
    add_table(
        story,
        ["Track", "Initial delivery", "Hardening", "Total estimate"],
        [
            ["Grafana direct DB", "4-7 dev days", "5-8 dev days", "9-15 dev days"],
            ["Custom PHP dashboards", "5-9 dev days", "3-6 dev days", "8-15 dev days"],
            ["Hybrid phase-1 PHP then Grafana", "6-10 dev days", "optional +4-7 days", "10-17 dev days"],
        ],
        [4.3 * cm, 3.8 * cm, 3.8 * cm, 4.5 * cm],
    )
    story.append(
        p(
            "Assumptions: existing MariaDB schema with crash/ticket/session tables, role data available; excludes major schema migration.",
            small,
        )
    )

    story.append(Spacer(1, 0.35 * cm))
    story.append(p("5. Recommendation under your constraints", h1))
    story.append(
        p(
            "• Do not introduce ETL/duplication. Keep one source of truth: MariaDB + live SQL views.<br/>"
            "• Implement a metrics SQL layer now (views/materialized semantics via SQL only, no copied store).<br/>"
            "• Build custom PHP dashboard pages first for guaranteed auth/session + slug scoping correctness.<br/>"
            "• Re-evaluate Grafana after metrics contract stabilizes; adopt only if direct DB + RBAC mapping is clean.",
            bullet,
        )
    )

    story.append(Spacer(1, 0.35 * cm))
    story.append(p("6. Proposed next implementation slice", h1))
    add_table(
        story,
        ["Step", "Deliverable", "ETA"],
        [
            ["1", "Define metrics dictionary + SQL views for user/slug/admin scopes", "1-2 days"],
            ["2", "Add heartbeat metric: time source in use + ntp correction savings counters", "0.5-1 day"],
            ["3", "Create PHP dashboards: user and slug-admin pages with 1d/7d selectors", "3-5 days"],
            ["4", "Add admin reliability board + crash/ticket links", "2-3 days"],
            ["5", "Optional Grafana POC over same SQL views", "2-3 days"],
        ],
        [1.2 * cm, 11.9 * cm, 3.3 * cm],
    )

    doc = SimpleDocTemplate(
        str(OUT_PDF),
        pagesize=A4,
        leftMargin=1.8 * cm,
        rightMargin=1.8 * cm,
        topMargin=1.6 * cm,
        bottomMargin=1.6 * cm,
        title="Grafana vs Others GraphVis Pivot",
        author="Android Cast project",
    )
    doc.build(story)
    print(f"Wrote {OUT_PDF}")


if __name__ == "__main__":
    build_pdf()
