"""BA PDF generator — Berita Acara Penjualan (Sales Shift Report)."""

import io
from datetime import datetime
from decimal import Decimal
from typing import Any


def _jakarta_now() -> str:
    from zoneinfo import ZoneInfo
    return datetime.now(ZoneInfo("Asia/Jakarta")).strftime("%d %B %Y %H:%M WIB")


def _fmt_rupiah(value: Any) -> str:
    try:
        v = int(Decimal(str(value)))
        return f"Rp {v:,}".replace(",", ".")
    except Exception:
        return str(value)


def _fmt_vol(value: Any, decimals: int = 3) -> str:
    try:
        v = Decimal(str(value))
        return f"{v:.{decimals}f} L"
    except Exception:
        return str(value)


def generate_ba_penjualan(
    spbu_name: str,
    spbu_code: str,
    tanggal: str,
    shift_nama: str,
    approver_name: str,
    nozzles: list[dict],
    total_volume: Decimal,
    total_nilai: Decimal,
    kas: dict,
) -> bytes:
    """
    Generate a Berita Acara Penjualan PDF.

    nozzles: list of dicts with keys:
        nozzle_nama, island_nama, produk_nama,
        teller_awal_manual, teller_akhir_manual,
        teller_awal_digital, teller_akhir_digital,
        primary_teller, volume, harga_jual, nilai

    kas: dict with keys:
        kas_100k, kas_50k, kas_20k, kas_10k, kas_5k, kas_2k, kas_1k, kas_logam,
        pembayaran_kartu, pembayaran_qr, pembayaran_instansi
    """
    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.platypus import Paragraph, SimpleDocTemplate, Spacer, Table, TableStyle

    buf = io.BytesIO()
    doc = SimpleDocTemplate(
        buf, pagesize=A4,
        leftMargin=1.5 * cm, rightMargin=1.5 * cm,
        topMargin=2 * cm, bottomMargin=2 * cm,
    )
    styles = getSampleStyleSheet()

    title_style = ParagraphStyle(
        "ba_title", parent=styles["Heading1"],
        fontSize=13, alignment=1, spaceAfter=2,
    )
    subtitle_style = ParagraphStyle(
        "ba_subtitle", parent=styles["Normal"],
        fontSize=11, alignment=1, spaceAfter=6,
    )
    small = ParagraphStyle(
        "ba_small", parent=styles["Normal"],
        fontSize=8, leading=12,
    )
    small_bold = ParagraphStyle(
        "ba_small_bold", parent=styles["Normal"],
        fontSize=8, leading=12, fontName="Helvetica-Bold",
    )
    normal = ParagraphStyle(
        "ba_normal", parent=styles["Normal"],
        fontSize=9, leading=13,
    )
    sig_style = ParagraphStyle(
        "ba_sig", parent=styles["Normal"],
        fontSize=9, alignment=1,
    )

    HEADER_BG = colors.Color(0.20, 0.37, 0.58)   # dark blue
    ROW_ALT   = colors.Color(0.95, 0.97, 1.0)
    GREY_BG   = colors.Color(0.93, 0.93, 0.93)

    story = []

    # ── Title block ────────────────────────────────────────────────────────────
    story.append(Paragraph("BERITA ACARA PENJUALAN", title_style))
    story.append(Paragraph(spbu_name, subtitle_style))
    story.append(Spacer(1, 0.3 * cm))

    meta_data = [
        [Paragraph("<b>Tanggal Laporan</b>", small), Paragraph(tanggal, small)],
        [Paragraph("<b>Shift</b>", small),            Paragraph(shift_nama, small)],
        [Paragraph("<b>Dicetak</b>", small),           Paragraph(_jakarta_now(), small)],
        [Paragraph("<b>Disetujui oleh</b>", small),    Paragraph(approver_name, small)],
    ]
    meta_table = Table(meta_data, colWidths=[4 * cm, 13 * cm])
    meta_table.setStyle(TableStyle([
        ("GRID",       (0, 0), (-1, -1), 0.3, colors.grey),
        ("BACKGROUND", (0, 0), (0, -1), GREY_BG),
        ("VALIGN",     (0, 0), (-1, -1), "MIDDLE"),
        ("TOPPADDING",    (0, 0), (-1, -1), 3),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 3),
    ]))
    story.append(meta_table)
    story.append(Spacer(1, 0.5 * cm))

    # ── Nozzle table ───────────────────────────────────────────────────────────
    story.append(Paragraph("<b>Data Penjualan per Nozzle</b>", normal))
    story.append(Spacer(1, 0.2 * cm))

    nozzle_header = [
        Paragraph("<font color='white'><b>Nozzle</b></font>", small_bold),
        Paragraph("<font color='white'><b>Island</b></font>", small_bold),
        Paragraph("<font color='white'><b>Produk</b></font>", small_bold),
        Paragraph("<font color='white'><b>Teller Awal</b></font>", small_bold),
        Paragraph("<font color='white'><b>Teller Akhir</b></font>", small_bold),
        Paragraph("<font color='white'><b>Volume (L)</b></font>", small_bold),
        Paragraph("<font color='white'><b>Harga/L</b></font>", small_bold),
        Paragraph("<font color='white'><b>Nilai (Rp)</b></font>", small_bold),
    ]
    nozzle_rows = [nozzle_header]

    for i, n in enumerate(nozzles):
        primary = n.get("primary_teller", "manual")
        teller_awal = n.get(f"teller_awal_{primary}", n.get("teller_awal_manual", 0))
        teller_akhir = n.get(f"teller_akhir_{primary}", n.get("teller_akhir_manual", 0))
        bg = ROW_ALT if i % 2 == 1 else colors.white
        row = [
            Paragraph(str(n.get("nozzle_nama", "")), small),
            Paragraph(str(n.get("island_nama", "")), small),
            Paragraph(str(n.get("produk_nama", "")), small),
            Paragraph(f"{Decimal(str(teller_awal)):.3f}", small),
            Paragraph(f"{Decimal(str(teller_akhir)):.3f}", small),
            Paragraph(f"{Decimal(str(n.get('volume', 0))):.3f}", small),
            Paragraph(_fmt_rupiah(n.get("harga_jual", 0)), small),
            Paragraph(_fmt_rupiah(n.get("nilai", 0)), small),
        ]
        nozzle_rows.append((row, bg))

    # Separate rows from bg info for TableStyle
    plain_rows = [nozzle_rows[0]] + [r[0] for r in nozzle_rows[1:]]
    col_widths = [2.5*cm, 2.2*cm, 2.5*cm, 2.4*cm, 2.4*cm, 2.2*cm, 2.5*cm, 3.3*cm]
    nozzle_table = Table(plain_rows, colWidths=col_widths, repeatRows=1)

    nozzle_style = [
        ("BACKGROUND", (0, 0), (-1, 0), HEADER_BG),
        ("GRID",       (0, 0), (-1, -1), 0.3, colors.grey),
        ("VALIGN",     (0, 0), (-1, -1), "MIDDLE"),
        ("TOPPADDING",    (0, 0), (-1, -1), 3),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 3),
        ("ALIGN",      (3, 1), (-1, -1), "RIGHT"),
    ]
    for i, (_, bg) in enumerate(nozzle_rows[1:], start=1):
        nozzle_style.append(("BACKGROUND", (0, i), (-1, i), bg))
    nozzle_table.setStyle(TableStyle(nozzle_style))
    story.append(nozzle_table)

    # ── Totals ─────────────────────────────────────────────────────────────────
    story.append(Spacer(1, 0.3 * cm))
    totals_data = [
        [Paragraph("<b>Total Volume</b>", small), Paragraph(_fmt_vol(total_volume), small)],
        [Paragraph("<b>Total Nilai</b>", small),  Paragraph(_fmt_rupiah(total_nilai), small)],
    ]
    totals_table = Table(totals_data, colWidths=[4 * cm, 6 * cm], hAlign="RIGHT")
    totals_table.setStyle(TableStyle([
        ("GRID",       (0, 0), (-1, -1), 0.3, colors.grey),
        ("BACKGROUND", (0, 0), (0, -1), GREY_BG),
        ("ALIGN",      (1, 0), (1, -1), "RIGHT"),
        ("TOPPADDING",    (0, 0), (-1, -1), 3),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 3),
    ]))
    story.append(totals_table)

    # ── Kas breakdown ──────────────────────────────────────────────────────────
    story.append(Spacer(1, 0.5 * cm))
    story.append(Paragraph("<b>Rincian Kas &amp; Pembayaran</b>", normal))
    story.append(Spacer(1, 0.2 * cm))

    # kas_100k etc. = JUMLAH LEMBAR (bill count), bukan Rupiah
    # Nilai Rupiah = lembar × denominasi
    KAS_DENOMS = [
        ("Rp 100.000", "kas_100k",  100_000),
        ("Rp 50.000",  "kas_50k",    50_000),
        ("Rp 20.000",  "kas_20k",    20_000),
        ("Rp 10.000",  "kas_10k",    10_000),
        ("Rp 5.000",   "kas_5k",      5_000),
        ("Rp 2.000",   "kas_2k",      2_000),
        ("Rp 1.000",   "kas_1k",      1_000),
        ("Logam",      "kas_logam",       1),   # kas_logam sudah Rupiah langsung
    ]
    kas_entries = [
        (label, int(kas.get(key, 0)), denom)
        for label, key, denom in KAS_DENOMS
    ]
    non_kas_entries = [
        ("Kartu/Debit",  kas.get("pembayaran_kartu", 0)),
        ("QR Code",      kas.get("pembayaran_qr", 0)),
        ("Instansi",     kas.get("pembayaran_instansi", 0)),
    ]

    total_kas = sum(Decimal(str(lembar * denom)) for _, lembar, denom in kas_entries)
    total_non_kas = sum(Decimal(str(v)) for _, v in non_kas_entries)

    kas_rows = [[
        Paragraph("<font color='white'><b>Pecahan</b></font>", small_bold),
        Paragraph("<font color='white'><b>Lembar</b></font>", small_bold),
        Paragraph("<font color='white'><b>Jumlah (Rp)</b></font>", small_bold),
        Paragraph("<font color='white'><b>Non-Kas</b></font>", small_bold),
        Paragraph("<font color='white'><b>Jumlah (Rp)</b></font>", small_bold),
    ]]
    max_rows = max(len(kas_entries), len(non_kas_entries))
    for i in range(max_rows):
        k_label, k_lembar, k_denom = kas_entries[i] if i < len(kas_entries) else ("", 0, 1)
        n_label, n_val = non_kas_entries[i] if i < len(non_kas_entries) else ("", "")
        k_rupiah = k_lembar * k_denom
        kas_rows.append([
            Paragraph(k_label, small),
            Paragraph(str(k_lembar) if k_label and k_lembar else "", small),
            Paragraph(_fmt_rupiah(k_rupiah) if k_label and k_lembar else "", small),
            Paragraph(n_label, small),
            Paragraph(_fmt_rupiah(n_val) if n_label else "", small),
        ])

    # Summary footer rows
    kas_rows.append([
        Paragraph("<b>Total Kas</b>", small_bold),
        Paragraph("", small),
        Paragraph(_fmt_rupiah(total_kas), small_bold),
        Paragraph("<b>Total Non-Kas</b>", small_bold),
        Paragraph(_fmt_rupiah(total_non_kas), small_bold),
    ])
    kas_rows.append([
        Paragraph("<b>Grand Total</b>", small_bold),
        Paragraph("", small),
        Paragraph("", small),
        Paragraph("", small),
        Paragraph(_fmt_rupiah(total_kas + total_non_kas), small_bold),
    ])

    kas_table = Table(kas_rows, colWidths=[3.0*cm, 1.5*cm, 3.5*cm, 3.5*cm, 3.5*cm])
    kas_style = [
        ("BACKGROUND", (0, 0), (-1, 0), HEADER_BG),
        ("GRID",       (0, 0), (-1, -1), 0.3, colors.grey),
        ("VALIGN",     (0, 0), (-1, -1), "MIDDLE"),
        ("TOPPADDING",    (0, 0), (-1, -1), 3),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 3),
        ("ALIGN",      (1, 1), (1, -1), "RIGHT"),  # lembar
        ("ALIGN",      (2, 1), (2, -1), "RIGHT"),  # rupiah kas
        ("ALIGN",      (4, 1), (4, -1), "RIGHT"),  # rupiah non-kas
        # Footer rows background
        ("BACKGROUND", (0, -2), (-1, -1), GREY_BG),
    ]
    for i in range(1, max_rows + 1):
        bg = ROW_ALT if (i - 1) % 2 == 1 else colors.white
        kas_style.append(("BACKGROUND", (0, i), (-1, i), bg))
    kas_table.setStyle(TableStyle(kas_style))
    story.append(kas_table)

    # ── Signature section ──────────────────────────────────────────────────────
    story.append(Spacer(1, 1.5 * cm))
    sig_data = [
        [
            Paragraph("Diserahkan oleh", sig_style), "",
            Paragraph("Diterima / Disetujui oleh", sig_style),
        ],
        [
            Paragraph("<br/><br/><br/>( _________________ )", sig_style), "",
            Paragraph(f"<br/><br/><br/>( {approver_name} )", sig_style),
        ],
    ]
    sig_table = Table(sig_data, colWidths=[7 * cm, 3 * cm, 7 * cm])
    sig_table.setStyle(TableStyle([
        ("ALIGN", (0, 0), (-1, -1), "CENTER"),
    ]))
    story.append(sig_table)

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