"""
Gerador de PDFs — App Reports
===================================
Gera PDFs profissionais com ReportLab para:
1. Fatura individual
2. Relatório diário de consultas
3. Relatório mensal financeiro

Identidade visual: Dra. Mariela Moreno Autie · Ginecologia · Luanda, Angola
Paleta: rosa #E8336A · dourado #D4AF37 · rosa claro #FDE8F0
"""

import io
from datetime import date
from decimal import Decimal

from reportlab.lib import colors
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
from reportlab.lib.units import cm, mm
from reportlab.platypus import (
    BaseDocTemplate,
    Frame,
    HRFlowable,
    NextPageTemplate,
    PageBreak,
    PageTemplate,
    Paragraph,
    Spacer,
    Table,
    TableStyle,
)

# ── Colores de marca ──────────────────────────────────────────
ROSA = colors.HexColor("#E8336A")
ROSA_LIGHT = colors.HexColor("#FDE8F0")
DORADO = colors.HexColor("#D4AF37")
DARK = colors.HexColor("#1A1A2E")
GRAY_500 = colors.HexColor("#6B7280")
GRAY_200 = colors.HexColor("#E5E7EB")
WHITE = colors.white

# ── Estilos base ──────────────────────────────────────────────
_styles = getSampleStyleSheet()


def _get_styles():
    """Retorna dicionário de estilos personalizados para PDFs."""
    return {
        "title": ParagraphStyle(
            "PDFTitle",
            parent=_styles["Title"],
            fontName="Helvetica-Bold",
            fontSize=18,
            textColor=ROSA,
            alignment=TA_LEFT,
            spaceAfter=2 * mm,
        ),
        "subtitle": ParagraphStyle(
            "PDFSubtitle",
            parent=_styles["Normal"],
            fontName="Helvetica",
            fontSize=10,
            textColor=GRAY_500,
            alignment=TA_LEFT,
            spaceAfter=4 * mm,
        ),
        "section": ParagraphStyle(
            "PDFSection",
            parent=_styles["Heading2"],
            fontName="Helvetica-Bold",
            fontSize=12,
            textColor=DARK,
            spaceBefore=6 * mm,
            spaceAfter=3 * mm,
        ),
        "normal": ParagraphStyle(
            "PDFNormal",
            parent=_styles["Normal"],
            fontName="Helvetica",
            fontSize=9,
            textColor=DARK,
            leading=13,
        ),
        "normal_right": ParagraphStyle(
            "PDFNormalRight",
            parent=_styles["Normal"],
            fontName="Helvetica",
            fontSize=9,
            textColor=DARK,
            alignment=TA_RIGHT,
        ),
        "bold": ParagraphStyle(
            "PDFBold",
            parent=_styles["Normal"],
            fontName="Helvetica-Bold",
            fontSize=9,
            textColor=DARK,
        ),
        "total": ParagraphStyle(
            "PDFTotal",
            parent=_styles["Normal"],
            fontName="Helvetica-Bold",
            fontSize=12,
            textColor=ROSA,
            alignment=TA_RIGHT,
        ),
        "footer": ParagraphStyle(
            "PDFFooter",
            parent=_styles["Normal"],
            fontName="Helvetica",
            fontSize=7,
            textColor=GRAY_500,
            alignment=TA_CENTER,
        ),
        "header_name": ParagraphStyle(
            "HeaderName",
            parent=_styles["Normal"],
            fontName="Helvetica-Bold",
            fontSize=14,
            textColor=ROSA,
            leading=17,
        ),
        "header_detail": ParagraphStyle(
            "HeaderDetail",
            parent=_styles["Normal"],
            fontName="Helvetica",
            fontSize=8,
            textColor=GRAY_500,
            leading=11,
        ),
    }


def _kz(amount):
    """Formata um valor como Kwanza."""
    if amount is None:
        return "0,00 Kz"
    return f"{amount:,.2f} Kz".replace(",", "X").replace(".", ",").replace("X", ".")


# ── Encabezado y pie de página ────────────────────────────────
def _draw_header_footer(canvas, doc, report_title=""):
    """Desenha cabeçalho e rodapé em cada página."""
    canvas.saveState()
    width, height = A4

    # ── ENCABEZADO ──
    # Franja rosa superior
    canvas.setFillColor(ROSA)
    canvas.rect(0, height - 18 * mm, width, 18 * mm, fill=1, stroke=0)

    # Línea dorada debajo
    canvas.setFillColor(DORADO)
    canvas.rect(0, height - 19.5 * mm, width, 1.5 * mm, fill=1, stroke=0)

    # Texto en la franja
    canvas.setFillColor(WHITE)
    canvas.setFont("Helvetica-Bold", 12)
    canvas.drawString(2 * cm, height - 11 * mm, "Dra. Mariela Moreno Autie")
    canvas.setFont("Helvetica", 8)
    canvas.drawString(2 * cm, height - 15 * mm, "Ginecologia  ·  Luanda, Angola")

    # Info derecha
    canvas.setFont("Helvetica", 7)
    canvas.drawRightString(width - 2 * cm, height - 10 * mm, "dramarielaautie@medcatalogo.com")
    canvas.drawRightString(width - 2 * cm, height - 14 * mm, "medcatalogo.com")

    # ── PIE DE PÁGINA ──
    canvas.setFillColor(GRAY_200)
    canvas.rect(0, 0, width, 14 * mm, fill=1, stroke=0)
    canvas.setFillColor(DORADO)
    canvas.rect(0, 14 * mm, width, 0.5 * mm, fill=1, stroke=0)

    canvas.setFillColor(GRAY_500)
    canvas.setFont("Helvetica", 7)
    canvas.drawString(2 * cm, 6 * mm, f"Gerado em {date.today().strftime('%d/%m/%Y')}")
    if report_title:
        canvas.drawCentredString(width / 2, 6 * mm, report_title)
    canvas.drawRightString(
        width - 2 * cm, 6 * mm, f"Página {doc.page}"
    )

    # Aviso legal
    canvas.setFont("Helvetica-Oblique", 6)
    canvas.drawCentredString(
        width / 2,
        2 * mm,
        "Este documento é gerado eletronicamente e não requer assinatura.",
    )

    canvas.restoreState()


def _build_doc(buffer, report_title=""):
    """Cria um BaseDocTemplate com frames, cabeçalho e rodapé."""
    width, height = A4
    doc = BaseDocTemplate(
        buffer,
        pagesize=A4,
        leftMargin=2 * cm,
        rightMargin=2 * cm,
        topMargin=2.5 * cm,
        bottomMargin=2 * cm,
    )

    frame = Frame(
        doc.leftMargin,
        doc.bottomMargin + 4 * mm,
        width - doc.leftMargin - doc.rightMargin,
        height - doc.topMargin - doc.bottomMargin - 8 * mm,
        id="main",
    )

    def _on_page(canvas, doc):
        _draw_header_footer(canvas, doc, report_title)

    template = PageTemplate(id="main", frames=[frame], onPage=_on_page)
    doc.addPageTemplates([template])
    return doc


# ── Estilos de tabla compartidos ──────────────────────────────
def _table_style_base():
    """Estilo base para tabelas de dados."""
    return TableStyle([
        # Encabezado
        ("BACKGROUND", (0, 0), (-1, 0), ROSA),
        ("TEXTCOLOR", (0, 0), (-1, 0), WHITE),
        ("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
        ("FONTSIZE", (0, 0), (-1, 0), 8),
        ("BOTTOMPADDING", (0, 0), (-1, 0), 6),
        ("TOPPADDING", (0, 0), (-1, 0), 6),
        # Cuerpo
        ("FONTNAME", (0, 1), (-1, -1), "Helvetica"),
        ("FONTSIZE", (0, 1), (-1, -1), 8),
        ("BOTTOMPADDING", (0, 1), (-1, -1), 4),
        ("TOPPADDING", (0, 1), (-1, -1), 4),
        # Grid suave
        ("GRID", (0, 0), (-1, -1), 0.3, GRAY_200),
        ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
    ])


def _add_alternating_rows(style, row_count):
    """Adiciona linhas alternadas em rosa claro."""
    for i in range(1, row_count):
        if i % 2 == 0:
            style.add("BACKGROUND", (0, i), (-1, i), ROSA_LIGHT)
    return style


# ══════════════════════════════════════════════════════════════
# 1. FACTURA INDIVIDUAL PDF
# ══════════════════════════════════════════════════════════════
def generar_factura_pdf(invoice):
    """
    Gera o PDF de uma fatura individual.
    Retorna bytes do PDF.
    """
    buffer = io.BytesIO()
    styles = _get_styles()
    doc = _build_doc(buffer, f"Fatura {invoice.numero}")
    story = []

    # ── Título ──
    story.append(Spacer(1, 4 * mm))
    story.append(Paragraph(f"FATURA {invoice.numero}", styles["title"]))
    story.append(
        Paragraph(
            f"Data de emissão: {invoice.fecha_emision.strftime('%d/%m/%Y %H:%M')}",
            styles["subtitle"],
        )
    )
    story.append(HRFlowable(width="100%", thickness=0.5, color=DORADO, spaceAfter=4 * mm))

    # ── Datos del paciente y clínica (2 columnas) ──
    left_data = [
        [Paragraph("<b>DADOS DO PACIENTE</b>", styles["bold"])],
        [Paragraph(invoice.paciente.get_full_name(), styles["normal"])],
        [Paragraph(invoice.paciente.email, styles["normal"])],
    ]
    if invoice.paciente.telefono:
        left_data.append([Paragraph(invoice.paciente.telefono, styles["normal"])])

    right_data = [
        [Paragraph("<b>DADOS DA CLÍNICA</b>", styles["bold"])],
    ]
    if invoice.clinica:
        right_data.append([Paragraph(invoice.clinica.nombre, styles["normal"])])
        if invoice.clinica.direccion:
            right_data.append([Paragraph(invoice.clinica.direccion, styles["normal"])])
        if invoice.clinica.nif:
            right_data.append([Paragraph(f"NIF: {invoice.clinica.nif}", styles["normal"])])
    else:
        right_data.append([Paragraph("Consultório Dra. Mariela", styles["normal"])])
        right_data.append([Paragraph("Luanda, Angola", styles["normal"])])

    # Pad to same length
    max_len = max(len(left_data), len(right_data))
    while len(left_data) < max_len:
        left_data.append([""])
    while len(right_data) < max_len:
        right_data.append([""])

    info_data = [[left_data[i][0], right_data[i][0]] for i in range(max_len)]
    info_table = Table(info_data, colWidths=[8.5 * cm, 8.5 * cm])
    info_table.setStyle(TableStyle([
        ("VALIGN", (0, 0), (-1, -1), "TOP"),
        ("LEFTPADDING", (0, 0), (-1, -1), 0),
        ("RIGHTPADDING", (0, 0), (-1, -1), 0),
    ]))
    story.append(info_table)
    story.append(Spacer(1, 6 * mm))

    # ── Detalle del servicio ──
    story.append(Paragraph("DETALHE", styles["section"]))

    service_data = [
        ["Serviço", "Data Consulta", "Duração", "Subtotal (Kz)"],
        [
            invoice.servicio.nombre,
            invoice.cita.fecha_hora.strftime("%d/%m/%Y %H:%M"),
            f"{invoice.cita.duracion_minutos} min",
            _kz(invoice.subtotal),
        ],
    ]
    service_table = Table(service_data, colWidths=[6 * cm, 4 * cm, 3 * cm, 4 * cm])
    style = _table_style_base()
    style.add("ALIGN", (2, 0), (3, -1), "RIGHT")
    service_table.setStyle(style)
    story.append(service_table)
    story.append(Spacer(1, 6 * mm))

    # ── Resumen financiero ──
    totals_data = [
        ["", "Subtotal:", _kz(invoice.subtotal)],
        ["", "IRT (Imposto):", _kz(invoice.irt)],
        ["", "TOTAL:", _kz(invoice.total)],
    ]
    totals_table = Table(totals_data, colWidths=[8.5 * cm, 4.5 * cm, 4 * cm])
    totals_table.setStyle(TableStyle([
        ("FONTNAME", (1, 0), (1, -1), "Helvetica"),
        ("FONTSIZE", (0, 0), (-1, -1), 9),
        ("ALIGN", (1, 0), (-1, -1), "RIGHT"),
        ("TEXTCOLOR", (0, 0), (-1, 1), DARK),
        # Total row bold + rosa
        ("FONTNAME", (1, 2), (-1, 2), "Helvetica-Bold"),
        ("FONTSIZE", (1, 2), (-1, 2), 12),
        ("TEXTCOLOR", (1, 2), (-1, 2), ROSA),
        ("LINEABOVE", (1, 2), (-1, 2), 1, DORADO),
        ("TOPPADDING", (0, 2), (-1, 2), 6),
    ]))
    story.append(totals_table)
    story.append(Spacer(1, 6 * mm))

    # ── Estado y método de pago ──
    estado_text = invoice.get_estado_display()
    metodo_text = invoice.get_metodo_pago_display() if invoice.metodo_pago else "—"
    info_line = f"<b>Estado:</b> {estado_text}  ·  <b>Método de pagamento:</b> {metodo_text}"
    story.append(Paragraph(info_line, styles["normal"]))

    # ── Pagos registrados ──
    pagos = invoice.pagos.filter(is_active=True).select_related("registrado_por").order_by("fecha")
    if pagos.exists():
        story.append(Spacer(1, 4 * mm))
        story.append(Paragraph("PAGAMENTOS REGISTRADOS", styles["section"]))
        pago_data = [["Data", "Valor", "Método", "Referência"]]
        for p in pagos:
            pago_data.append([
                p.fecha.strftime("%d/%m/%Y %H:%M"),
                _kz(p.monto),
                p.get_metodo_display(),
                p.referencia or "—",
            ])
        pago_table = Table(pago_data, colWidths=[4 * cm, 4 * cm, 4.5 * cm, 4.5 * cm])
        pstyle = _table_style_base()
        pstyle.add("ALIGN", (1, 0), (1, -1), "RIGHT")
        _add_alternating_rows(pstyle, len(pago_data))
        pago_table.setStyle(pstyle)
        story.append(pago_table)

    doc.build(story)
    buffer.seek(0)
    return buffer.getvalue()


# ══════════════════════════════════════════════════════════════
# 2. REPORTE DIARIO DE CITAS PDF
# ══════════════════════════════════════════════════════════════
def generar_reporte_diario_pdf(fecha, citas, ingresos_dia):
    """
    Gera relatório de consultas do dia.
    citas: queryset de Cita do dia (com select_related).
    ingresos_dia: Decimal com o total de receitas.
    Retorna bytes do PDF.
    """
    buffer = io.BytesIO()
    styles = _get_styles()
    doc = _build_doc(buffer, f"Relatório Diário — {fecha.strftime('%d/%m/%Y')}")
    story = []

    story.append(Spacer(1, 4 * mm))
    story.append(Paragraph("RELATÓRIO DIÁRIO DE CONSULTAS", styles["title"]))
    story.append(
        Paragraph(
            f"Data: {fecha.strftime('%A, %d de %B de %Y').title()}",
            styles["subtitle"],
        )
    )
    story.append(HRFlowable(width="100%", thickness=0.5, color=DORADO, spaceAfter=4 * mm))

    # ── Tabla de citas ──
    if citas:
        story.append(Paragraph("CONSULTAS DO DIA", styles["section"]))

        cita_data = [["Hora", "Paciente", "Serviço", "Estado", "Duração"]]
        for c in citas:
            cita_data.append([
                c.fecha_hora.strftime("%H:%M"),
                c.paciente.get_full_name(),
                c.servicio.nombre,
                c.get_estado_display(),
                f"{c.duracion_minutos} min",
            ])

        cita_table = Table(
            cita_data,
            colWidths=[2.5 * cm, 5 * cm, 4.5 * cm, 3 * cm, 2 * cm],
        )
        cstyle = _table_style_base()
        _add_alternating_rows(cstyle, len(cita_data))
        cstyle.add("ALIGN", (4, 0), (4, -1), "CENTER")
        cita_table.setStyle(cstyle)
        story.append(cita_table)
    else:
        story.append(Spacer(1, 10 * mm))
        story.append(Paragraph("Não há consultas registradas para este dia.", styles["normal"]))

    # ── Resumen ──
    story.append(Spacer(1, 8 * mm))
    story.append(Paragraph("RESUMO DO DIA", styles["section"]))

    # Conteo por estado
    from collections import Counter
    estados = Counter(c.estado for c in citas)

    summary_data = [["Indicador", "Quantidade"]]
    summary_data.append(["Total de consultas", str(len(citas))])
    for estado, count in sorted(estados.items()):
        # Get display name
        from apps.appointments.models import Cita
        display = dict(Cita.Estado.choices).get(estado, estado)
        summary_data.append([f"  {display}", str(count)])
    summary_data.append(["Receitas do dia", _kz(ingresos_dia)])

    summary_table = Table(summary_data, colWidths=[10 * cm, 7 * cm])
    sstyle = _table_style_base()
    sstyle.add("ALIGN", (1, 0), (1, -1), "RIGHT")
    # Last row bold
    sstyle.add("FONTNAME", (0, -1), (-1, -1), "Helvetica-Bold")
    sstyle.add("TEXTCOLOR", (1, -1), (1, -1), ROSA)
    _add_alternating_rows(sstyle, len(summary_data))
    summary_table.setStyle(sstyle)
    story.append(summary_table)

    doc.build(story)
    buffer.seek(0)
    return buffer.getvalue()


# ══════════════════════════════════════════════════════════════
# 3. REPORTE MENSUAL FINANCIERO PDF
# ══════════════════════════════════════════════════════════════
def generar_reporte_mensual_pdf(year, month, clinica_stats, grand):
    """
    Gera relatório financeiro mensal agrupado por clínica.
    clinica_stats: lista de dicts com clinica_nombre, total_pventa, total_medico, total_irt, total_neto, num_facturas.
    grand: dict com totais gerais.
    Retorna bytes do PDF.
    """

    buffer = io.BytesIO()
    styles = _get_styles()

    meses = {
        1: "Janeiro", 2: "Fevereiro", 3: "Março", 4: "Abril",
        5: "Maio", 6: "Junho", 7: "Julho", 8: "Agosto",
        9: "Setembro", 10: "Outubro", 11: "Novembro", 12: "Dezembro",
    }
    mes_nombre = meses.get(month, str(month))

    doc = _build_doc(buffer, f"Relatório Financeiro — {mes_nombre} {year}")
    story = []

    story.append(Spacer(1, 4 * mm))
    story.append(Paragraph("RELATÓRIO MENSAL FINANCEIRO", styles["title"]))
    story.append(Paragraph(f"Período: {mes_nombre} {year}", styles["subtitle"]))
    story.append(HRFlowable(width="100%", thickness=0.5, color=DORADO, spaceAfter=6 * mm))

    # ── Tabla por clínica ──
    story.append(Paragraph("RECEITAS POR CLÍNICA", styles["section"]))

    if clinica_stats:
        table_data = [
            ["Clínica", "Fat.", "P. Venda Total", "% Médico Total", "IRT Total", "Receita Líquida"],
        ]
        for stat in clinica_stats:
            table_data.append([
                Paragraph(f'<b>{stat["clinica_nombre"] or "Sem Clínica"}</b>', styles["normal"]),
                str(stat["num_facturas"]),
                _kz(stat["total_pventa"]),
                _kz(stat["total_medico"]),
                _kz(stat["total_irt"]),
                _kz(stat["total_neto"]),
            ])

        # Fila de totales
        table_data.append([
            Paragraph('<b>TOTALES</b>', styles["normal"]),
            str(grand["num_facturas"]),
            _kz(grand["total_pventa"]),
            _kz(grand["total_medico"]),
            _kz(grand["total_irt"]),
            _kz(grand["total_neto"]),
        ])

        table = Table(table_data, colWidths=[4.5 * cm, 1.5 * cm, 3 * cm, 3 * cm, 2.5 * cm, 3 * cm])
        style = _clinica_table_style(len(table_data))
        table.setStyle(style)
        story.append(table)

        # Resumen destacado
        story.append(Spacer(1, 5 * mm))
        resumen = (
            f"<b>Total Faturas:</b> {grand['num_facturas']}  ·  "
            f"<b>P. Venda:</b> {_kz(grand['total_pventa'])}  ·  "
            f"<b>Receita Líquida:</b> <font color='#E8336A'><b>{_kz(grand['total_neto'])}</b></font>"
        )
        story.append(Paragraph(resumen, styles["normal"]))
    else:
        story.append(Paragraph("Não há faturas registradas para este período.", styles["normal"]))

    doc.build(story)
    buffer.seek(0)
    return buffer.getvalue()


def _clinica_table_style(num_rows):
    """Estilo compartilhado para tabelas de clínica (mensal e anual)."""
    HEADER_BG = colors.HexColor("#2C3E50")
    SOFT_ROW = colors.HexColor("#F0F4F8")
    ACCENT = colors.HexColor("#2980B9")
    last_row = num_rows - 1
    style = TableStyle([
        # Encabezado
        ("BACKGROUND", (0, 0), (-1, 0), HEADER_BG),
        ("TEXTCOLOR", (0, 0), (-1, 0), WHITE),
        ("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
        ("FONTSIZE", (0, 0), (-1, 0), 9),
        ("BOTTOMPADDING", (0, 0), (-1, 0), 8),
        ("TOPPADDING", (0, 0), (-1, 0), 8),
        # Cuerpo
        ("FONTNAME", (0, 1), (-1, -1), "Helvetica"),
        ("FONTSIZE", (0, 1), (-1, -1), 9),
        ("BOTTOMPADDING", (0, 1), (-1, -1), 6),
        ("TOPPADDING", (0, 1), (-1, -1), 6),
        # Alineación
        ("ALIGN", (1, 0), (-1, -1), "RIGHT"),
        ("ALIGN", (0, 0), (0, -1), "LEFT"),
        # Bordes
        ("LINEBELOW", (0, 0), (-1, 0), 1.2, ACCENT),
        ("LINEABOVE", (0, last_row), (-1, last_row), 1.2, ACCENT),
        ("LINEBELOW", (0, last_row), (-1, last_row), 1.2, HEADER_BG),
        ("GRID", (0, 0), (-1, -1), 0.3, GRAY_200),
        ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
        # Fila totales
        ("BACKGROUND", (0, last_row), (-1, last_row), colors.HexColor("#D6EAF8")),
        ("FONTNAME", (0, last_row), (-1, last_row), "Helvetica-Bold"),
        ("FONTSIZE", (0, last_row), (-1, last_row), 10),
        ("TOPPADDING", (0, last_row), (-1, last_row), 8),
        ("BOTTOMPADDING", (0, last_row), (-1, last_row), 8),
    ])
    # Filas alternas
    for i in range(1, last_row):
        if i % 2 == 0:
            style.add("BACKGROUND", (0, i), (-1, i), SOFT_ROW)
    return style


def generar_reporte_anual_pdf(year, meses_data, grand):
    """
    Gera relatório financeiro anual com 12 meses em horizontal.
    meses_data: lista de 12 dicts por clínica, cada um com nome e dados mensais.
    grand: dict com totais por mês e grande total.
    Retorna bytes do PDF.
    """
    from reportlab.lib.pagesizes import landscape, A4

    buffer = io.BytesIO()
    styles = _get_styles()
    width, height = landscape(A4)

    # Doc especial landscape
    doc = BaseDocTemplate(
        buffer,
        pagesize=landscape(A4),
        leftMargin=1.2 * cm,
        rightMargin=1.2 * cm,
        topMargin=2.5 * cm,
        bottomMargin=2 * cm,
    )

    frame = Frame(
        doc.leftMargin,
        doc.bottomMargin + 4 * mm,
        width - doc.leftMargin - doc.rightMargin,
        height - doc.topMargin - doc.bottomMargin - 8 * mm,
        id="main",
    )

    def _on_page(canvas, doc):
        _draw_header_footer(canvas, doc, f"Relatório Anual — {year}")

    template = PageTemplate(id="main", frames=[frame], onPage=_on_page)
    doc.addPageTemplates([template])

    story = []

    MESES_CORTOS = ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"]

    story.append(Spacer(1, 2 * mm))
    story.append(Paragraph(f"RELATÓRIO ANUAL FINANCEIRO — {year}", styles["title"]))
    story.append(HRFlowable(width="100%", thickness=0.5, color=DORADO, spaceAfter=4 * mm))

    # ── Tabla P. Venta por mes ──
    _add_annual_section(story, styles, "PREÇO VENDA POR MÊS", meses_data, grand, "pventa", MESES_CORTOS)
    story.append(Spacer(1, 4 * mm))

    # ── Tabla % Médico por mes ──
    _add_annual_section(story, styles, "% MÉDICO POR MÊS", meses_data, grand, "medico", MESES_CORTOS)
    story.append(Spacer(1, 4 * mm))

    # ── Tabla IRT por mes ──
    _add_annual_section(story, styles, "IRT POR MÊS", meses_data, grand, "irt", MESES_CORTOS)
    story.append(Spacer(1, 4 * mm))

    # ── Tabla Ingreso Neto por mes ──
    _add_annual_section(story, styles, "RECEITA LÍQUIDA POR MÊS", meses_data, grand, "neto", MESES_CORTOS)

    doc.build(story)
    buffer.seek(0)
    return buffer.getvalue()


def _add_annual_section(story, styles, title, meses_data, grand, field_key, meses_cortos):
    """Adiciona uma tabela de clínica x meses para um campo específico."""
    story.append(Paragraph(title, styles["section"]))

    header = ["Clínica"] + meses_cortos + ["TOTAL"]
    table_data = [header]

    for clinica in meses_data:
        row_data = [Paragraph(f'<b>{clinica["nombre"]}</b>', ParagraphStyle("t", fontName="Helvetica-Bold", fontSize=7, textColor=DARK))]
        for m in range(1, 13):
            val = clinica["meses"].get(m, {}).get(field_key, Decimal("0"))
            row_data.append(_kz(val))
        row_data.append(_kz(clinica["total_" + field_key]))
        table_data.append(row_data)

    # Fila totales
    total_row = [Paragraph('<b>TOTALES</b>', ParagraphStyle("t", fontName="Helvetica-Bold", fontSize=7, textColor=DARK))]
    for m in range(1, 13):
        total_row.append(_kz(grand["meses"].get(m, {}).get(field_key, Decimal("0"))))
    total_row.append(_kz(grand["total_" + field_key]))
    table_data.append(total_row)

    # Anchos: clínica + 12 meses + total
    col_w = [3.2 * cm] + [1.7 * cm] * 12 + [2 * cm]
    table = Table(table_data, colWidths=col_w)

    style = _clinica_table_style(len(table_data))
    # Ajustar tamaño fuente para que quepa
    style.add("FONTSIZE", (0, 0), (-1, 0), 7)
    style.add("FONTSIZE", (0, 1), (-1, -1), 7)
    table.setStyle(style)
    story.append(table)
