from reportlab.platypus import (
    SimpleDocTemplate,
    Paragraph,
    Spacer,
    Table,
    TableStyle,
    PageBreak,
)
from reportlab.lib.pagesizes import A4
    # A4 = (595.27 , 841.89)
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import mm
from pathlib import Path
import os
from typing import Dict, Any, Optional

def build_tax_lookup_basic_section(
    tax_lookup_basic: Dict[str, Any],
    H2: ParagraphStyle,
    small: ParagraphStyle,
):
    """
    Construye la sección de ABN Lookup (básico) como una lista de Flowables
    para agregar al story de ReportLab.
    """
    elements = []

    # Título
    elements.append(Paragraph("Supplier Registry Lookup (ABN – basic)", H2))

    abn = tax_lookup_basic.get("tax_id") or "N/A"
    entity_name = tax_lookup_basic.get("entity_name") or "No disponible"

    abn_exists = bool(tax_lookup_basic.get("abn_exists"))
    is_active = bool(tax_lookup_basic.get("is_active"))
    gst_registered = bool(tax_lookup_basic.get("gst_registered"))

    if not abn_exists:
        estado_abn = "No encontrado en el registro oficial"
    else:
        estado_abn = "Activo" if is_active else "Inactivo / Cancelado"

    if gst_registered:
        gst_text = "Registrado para GST"
    else:
        gst_text = "No registrado para GST (o sin información)"

    table_data = [
        ["ABN", abn],
        ["Nombre registrado", entity_name],
        ["Estado ABN", estado_abn],
        ["GST", gst_text],
    ]

    tbl = Table(table_data, colWidths=[35 * mm, 90 * mm])
    tbl.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (0, -1), colors.aqua),
        ("FONTNAME", (0, 0), (-1, -1), "Helvetica"),
        ("FONTSIZE", (0, 0), (-1, -1), 9),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 3),
        ("VALIGN", (0, 0), (-1, -1), "TOP"),
    ]))

    elements.append(tbl)
    elements.append(Spacer(1, 4))

    # Nota pequeña tipo marketing / contexto
    note_html = (
        '<font size="7" color="grey">'
        'Information provided by tax lookup service (basic version). '
        'For extended validation, connect the full ABN Lookup app.'
        '</font>'
    )
    elements.append(Paragraph(note_html, small))
    elements.append(Spacer(1, 8))

    return elements

def create_invoice_revision_pdf(
    extracted: Dict[str, Any],
    output_dir: str,
    original_filename: str,
    checks: Optional[Dict[str, Any]] = None,
) -> str:
    """
    Layout universal v1:

    Página 1:
      - Título
      - DOS COLUMNAS:
        Izquierda: Header Information, Supplier Details, Buyer Details
        Derecha: Payment Info (as printed), Internal Payment Information

    Página 2+:
      - Line Items (tabla, con repeatRows para el header; puede ocupar varias páginas)

    Página final:
      - Financial Summary
      - Validation Checks
    """

    # -------------------------------
    # 0. Paths y documento
    # -------------------------------
    out_path = Path(output_dir)
    out_path.mkdir(parents=True, exist_ok=True)

    safe_name = original_filename or "invoice"
    stem = os.path.splitext(safe_name)[0]
    pdf_path = out_path / f"{stem}_universal.pdf"

    styles = getSampleStyleSheet()

    H1 = ParagraphStyle(
        "H1",
        parent=styles["Heading1"],
        fontSize=15,
        leading=18,
        spaceAfter=6,
    )
    H2 = ParagraphStyle(
        "H2",
        parent=styles["Heading2"],
        fontSize=12,
        leading=14,
        spaceBefore=6,
        spaceAfter=4,
    )
    normal = styles["Normal"]
    small = ParagraphStyle("small", parent=normal, fontSize=8, leading=9)
    small_item = ParagraphStyle("small_item", parent=small, fontSize=7.5, leading=9)

    doc = SimpleDocTemplate(
        str(pdf_path),
        pagesize=A4,
        leftMargin=22 * mm,
        rightMargin=22 * mm,
        topMargin=20 * mm,
        bottomMargin=20 * mm,
    )

    page_width, _ = A4
    content_width = page_width - doc.leftMargin - doc.rightMargin
    col_width = content_width / 2.0

    story = []

    # Helper para acceder a rutas tipo "header.invoice.date.issue_date.verbatim"
    def get_node(path: str, default=None):
        parts = path.split(".")
        node: Any = extracted
        for p in parts:
            if not isinstance(node, dict):
                return default
            node = node.get(p)
            if node is None:
                return default
        return node if node is not None else default

    # -------------------------------
    # 1. Título + disclaimer
    # -------------------------------
    inv_number = get_node("header.invoice.number.verbatim")
    inv_date = get_node("header.invoice.date.issue_date.verbatim")
    supplier_name = get_node("header.supplier.name.verbatim")

    title_text = f"{supplier_name or 'Supplier'} – Invoice Extract – {inv_number or 'N/A'} – {inv_date or 'N/A'}"
    story.append(Paragraph(title_text, H1))

    disclaimer = """<font size="7" color="grey">
    This document is an automatically generated digital extract from an original supplier invoice.
    It is NOT a legally issued tax invoice.
    </font>"""
    story.append(Paragraph(disclaimer, small))
    story.append(Spacer(1, 6))

    # -------------------------------
    # 2. Bloques de resumen (dos columnas)
    # -------------------------------

    # 2.1 Header Information
    header_data = [
        ["Invoice Number:", inv_number or "N/A"],
        ["Issue Date:", inv_date or "N/A"],
        ["Invoice Type:", get_node("invoice_type.verbatim") or "N/A"],
    ]
    header_tbl = Table(header_data, colWidths=[30 * mm, col_width - 30 * mm])
    header_tbl.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (0, -1), colors.beige),
        ("FONTNAME", (0, 0), (-1, -1), "Helvetica"),
        ("FONTSIZE", (0, 0), (-1, -1), 9),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 3),
    ]))

    # 2.2 Supplier Details
    sup = extracted.get("header", {}).get("supplier", {}) or {}
    sup_name = (
        sup.get("name", {}).get("verbatim")
        or sup.get("name", {}).get("computed")
        or ""
    )

    sup_abn = (
        sup.get("abn", {}).get("verbatim")
        or sup.get("abn", {}).get("computed")
        or ""
    )
    sup_address = sup.get("address", {}).get("verbatim") or sup.get("address", {}).get("computed")
    supplier_table = [
        ["Name", sup_name],
        ["ABN", sup_abn],
        ["Address", Paragraph(sup_address or "", small)],
        ["Phone", sup.get("phone", {}).get("verbatim", {})],
        ["Email", sup.get("email", {}).get("verbatim", {})],
    ]
    supplier_tbl = Table(supplier_table, colWidths=[25 * mm, col_width - 25 * mm])
    supplier_tbl.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (0, -1), colors.bisque),
        ("FONTNAME", (0, 0), (-1, -1), "Helvetica"),
        ("FONTSIZE", (0, 0), (-1, -1), 9),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 3),
    ]))

    # 2.3 Buyer Details (NUEVA SECCIÓN)
    buyer = extracted.get("header", {}).get("buyer", {}) or {}
    printed_address = (buyer.get("address") or {}).get("verbatim") if isinstance(buyer.get("address"), dict) else "None"
    buyer_table = [
        ["Name", (buyer.get("name") or {}).get("verbatim")],
        ["ABN", (buyer.get("abn") or {}).get("verbatim")],
        ["Address", Paragraph(printed_address, small)],
        ["Phone", (buyer.get("phone") or {}).get("verbatim") if isinstance(buyer.get("phone"), dict) else None],
        ["Email", (buyer.get("email") or {}).get("verbatim") if isinstance(buyer.get("email"), dict) else None],
    ]
    buyer_tbl = Table(buyer_table, colWidths=[25 * mm, col_width - 25 * mm])
    buyer_tbl.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (0, -1), colors.blanchedalmond),
        ("FONTNAME", (0, 0), (-1, -1), "Helvetica"),
        ("FONTSIZE", (0, 0), (-1, -1), 9),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 3),
    ]))

    # 2.4 Payment Info (as printed)
    pp = extracted.get("payment_printed", {}) or {}
    printed_rows = [
        ["Printed Status:", (pp.get("status") or {}).get("verbatim")],
        ["Amount Paid:", (pp.get("amount_paid") or {}).get("verbatim")],
        ["Balance Due:", (pp.get("balance_due") or {}).get("verbatim")],
        ["Method:", (pp.get("method") or {}).get("verbatim")],
        ["Reference:", (pp.get("reference") or {}).get("verbatim")],
    ]
    printed_tbl = Table(printed_rows, colWidths=[30 * mm, col_width - 30 * mm])
    printed_tbl.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (0, -1), colors.aquamarine),
        ("FONTNAME", (0, 0), (-1, -1), "Helvetica"),
        ("FONTSIZE", (0, 0), (-1, -1), 9),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 3),
    ]))

    printed_caption = Paragraph(
        """<font size="7" color="grey">
        Payment info above is shown exactly as printed on the supplier document.
        Actual reconciliation is done in Xero / AroFlo.
        </font>""",
        small,
    )

    # 2.5 Internal Payment Information (notes con wrap)
    pi = extracted.get("payment_interpretation", {}) or {}
    pi_status = pi.get("suggested_internal_status") or ""
    pi_flag = str(pi.get("is_pos_fully_paid")) if "is_pos_fully_paid" in pi else ""
    pi_notes_text = pi.get("notes") or ""

    interp_rows = [
        ["Internal Status:", pi_status],
        ["POS Fully Paid:", pi_flag],
        ["Notes:", Paragraph(pi_notes_text, small)],  # <--- wrap automático
    ]
    interp_tbl = Table(interp_rows, colWidths=[30 * mm, col_width - 30 * mm])
    interp_tbl.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (0, -1), colors.blueviolet),
        ("FONTNAME", (0, 0), (-1, -1), "Helvetica"),
        ("FONTSIZE", (0, 0), (-1, -1), 9),
        ("VALIGN", (0, 0), (-1, -1), "TOP"),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 3),
    ]))

    # 2.6 Empaquetar cada columna en su propia tabla vertical

    # Columna izquierda: Header + Supplier + Buyer
    left_rows = [
        [Paragraph("Header Information", H2)],
        [header_tbl],
        [Spacer(1, 12)],
        [Paragraph("Supplier Details", H2)],
        [supplier_tbl],
        [Spacer(1, 12)],
        [Paragraph("Buyer Details", H2)],
        [buyer_tbl],
    ]
    left_col_table = Table(left_rows, colWidths=[col_width])
    left_col_table.setStyle(TableStyle([
        ("VALIGN", (0, 0), (-1, -1), "TOP"),
        ("LEFTPADDING", (0, 0), (-1, -1), 0),
        ("RIGHTPADDING", (0, 0), (-1, -1), 6),
        ("TOPPADDING", (0, 0), (-1, -1), 0),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 0),
    ]))

    # Columna derecha: Payment printed + Internal Payment
    right_rows = [
        [Paragraph("Payment Info (as printed)", H2)],
        [printed_tbl],
        [Spacer(1, 12)],
        [printed_caption],
        [Spacer(1, 12)],
        [Paragraph("Internal Payment Information", H2)],
        [interp_tbl],
    ]
    right_col_table = Table(right_rows, colWidths=[col_width])
    right_col_table.setStyle(TableStyle([
        ("VALIGN", (0, 0), (-1, -1), "TOP"),
        ("LEFTPADDING", (0, 0), (-1, -1), 6),
        ("RIGHTPADDING", (0, 0), (-1, -1), 0),
        ("TOPPADDING", (0, 0), (-1, -1), 0),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 0),
    ]))

    # Tabla general de dos columnas
    two_col_summary = Table(
        [[left_col_table, right_col_table]],
        colWidths=[col_width, col_width],
        hAlign="LEFT",
    )
    two_col_summary.setStyle(TableStyle([
        ("VALIGN", (0, 0), (-1, -1), "TOP"),
        ("LEFTPADDING", (0, 0), (-1, -1), 0),
        ("RIGHTPADDING", (0, 0), (-1, -1), 0),
        ("TOPPADDING", (0, 0), (-1, -1), 0),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 0),
    ]))

    story.append(two_col_summary)

    # -------------------------------
    # 3. Página(s) de Line Items
    # -------------------------------
    story.append(PageBreak())
    story.append(Paragraph("Line Items", H2))

    items = extracted.get("items", []) or []

    table_header = ["SKU", "Description", "Qty", "Unit Price", "Discount", "GST", "Line Total"]
    table_rows = [[Paragraph(h, small_item) for h in table_header]]

    for item in items:
        def field(it, key):
            node = it.get(key) or {}
            return node.get("verbatim") or node.get("computed") or ""

        sku = field(item, "sku")
        desc = field(item, "description")
        qty = field(item, "qty")
        unit = field(item, "unit_price")
        disc = field(item, "discount")
        gst_line = field(item, "gst_line")
        line_total = field(item, "line_total")

        row = [
            Paragraph(str(sku), small_item),
            Paragraph(str(desc), small_item),
            Paragraph(str(qty), small_item),
            Paragraph(str(unit), small_item),
            Paragraph(str(disc), small_item),
            Paragraph(str(gst_line), small_item),
            Paragraph(str(line_total), small_item),
        ]
        table_rows.append(row)

    if table_rows:
        items_tbl = Table(
            table_rows,
            colWidths=[18 * mm, 70 * mm, 10 * mm, 18 * mm, 18 * mm, 14 * mm, 20 * mm],
            repeatRows=1,  # header se repite si ocupa varias páginas
        )
        items_tbl.setStyle(TableStyle([
            ("GRID", (0, 0), (-1, -1), 0.25, colors.grey),
            ("BACKGROUND", (0, 0), (-1, 0), colors.lightgrey),
            ("VALIGN", (0, 0), (-1, -1), "TOP"),
        ]))
        story.append(items_tbl)
    else:
        story.append(Paragraph("No line items found.", small))

        # -------------------------------
    # 4. Página final: Summary + Validations
    # -------------------------------
    story.append(PageBreak())

    totals = extracted.get("totals", {}) or {}

    def tval(key: str):
        node = totals.get(key) or {}
        return node.get("verbatim") or node.get("computed")

    summary_rows = [
        ["Subtotal", str(tval("subtotal"))],
        ["Discount Global", str(tval("discount_global"))],
        ["Freight", str(tval("freight"))],
        ["Surcharges", str(tval("surcharge_total"))],
        ["Rounding", str(tval("rounding"))],
        ["GST", str(tval("gst"))],
        ["Grand Total", str(tval("grand_total"))],
        ["GST Basis", totals.get("gst_basis", "")],
    ]

    summary_tbl = Table(summary_rows, colWidths=[40 * mm, 80 * mm])
    summary_tbl.setStyle(TableStyle([
        # Título: merge columnas 0–1
        ("SPAN", (0,0), (1,0)),
        ("BACKGROUND", (0,0), (1,0), colors.lightgrey),
        ("FONTNAME", (0,0), (1,0), "Helvetica-Bold"),
        ("FONTSIZE", (0,0), (1,0), 11),
        ("ALIGN", (0,0), (1,0), "CENTER"),
        ("BOTTOMPADDING", (0,0), (1,0), 6),
        ("TOPPADDING", (0,0), (1,0), 6),

        # Filas normales
        ("FONTNAME", (0,1), (-1,-1), "Helvetica"),
        ("FONTSIZE", (0,1), (-1,-1), 9),
        ("BACKGROUND", (0,1), (0,-1), colors.aliceblue),
        ("BOTTOMPADDING", (0,1), (-1,-1), 3),
    ]))

    story.append(Paragraph("Financial Summary", H2))
    story.append(summary_tbl)
    story.append(Spacer(1, 10))

    # --- NUEVO: sección ABN Lookup (básico), si hay checks ---
    if checks:
        tax_lookup_basic = checks.get("tax_lookup_basic")
        if tax_lookup_basic:
            story.extend(build_tax_lookup_basic_section(tax_lookup_basic, H2, small))

    # --- Validaciones internas ---
    validations = totals.get("validations", {}) or {}
    story.append(Paragraph("Validation Checks", H2))
    """ if validations:
        for k, v in validations.items():
            story.append(Paragraph(f"• {k}: <b>{v}</b>", small))
    else:
        story.append(Paragraph("No validations available.", small)) """
  
    validation_rows = []
    if validations:
        for key, value in validations.items():
            validation_rows.append([key, "\u2714" if value else "\u2718"])
        validations_tbl = Table(validation_rows, colWidths=[80 * mm, 40 * mm])
        validations_tbl.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (0, -1), colors.azure),
        ("FONTNAME", (0, 0), (-1, -1), "Helvetica"),
        ("FONTSIZE", (0, 0), (-1, -1), 9),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 3),
    ]))
        story.append(validations_tbl)
    else:
        story.append(Paragraph("No validations available.", small))
    story.append(Spacer(1, 10))
    minimum_ato_symbol = '\u2714' if extracted.get('minimum_ato', False) else '\u2718'
    minumym_xero_symbol = '\u2714' if extracted.get('minimum_xero_aeroflo', False) else '\u2718'
    data_validated_symbol = '\u2714' if extracted.get('date_validated', False) else '\u2718'
    story.append(Paragraph(
        f"minimum_ato: <b>{minimum_ato_symbol}</b> – "
        f"minimum_xero_aeroflo: <b>{minumym_xero_symbol}</b> – "
        f"date_validated: <b>{data_validated_symbol}</b>",
        small,
    ))

    

    # -------------------------------
    # 5. Build PDF
    # -------------------------------
    doc.build(story)
    return str(pdf_path)

from typing import Dict, Any
from reportlab.pdfgen.canvas import Canvas


def _draw_tax_lookup_basic_section(
    c: "Canvas",
    data: Dict[str, Any],
    x: float,
    y: float,
) -> float:
    """
    Dibuja en el PDF la sección de ABN Lookup (básico).
    Devuelve la nueva coordenada y (para seguir escribiendo debajo).
    """
    line_height = 12

    c.setFont("Helvetica-Bold", 11)
    c.drawString(x, y, "ABN Lookup (básico) – Australia")
    y -= line_height

    c.setFont("Helvetica", 9)
    abn = data.get("tax_id") or "N/D"
    entity_name = data.get("entity_name") or "No disponible"

    abn_exists = bool(data.get("abn_exists"))
    is_active = bool(data.get("is_active"))
    gst_registered = bool(data.get("gst_registered"))

    c.drawString(x, y, f"ABN: {abn}")
    y -= line_height
    c.drawString(x, y, f"Nombre registrado: {entity_name}")
    y -= line_height

    # Estado ABN
    if not abn_exists:
        estado_abn = "No encontrado en el registro oficial"
    else:
        estado_abn = "Activo" if is_active else "Inactivo / Cancelado"

    c.drawString(x, y, f"Estado ABN: {estado_abn}")
    y -= line_height

    # GST
    if gst_registered:
        gst_text = "Registrado para GST"
    else:
        gst_text = "No registrado para GST (o sin información)"

    c.drawString(x, y, f"GST: {gst_text}")
    y -= line_height

    # Nota pequeña de contexto / marketing
    c.setFont("Helvetica-Oblique", 8)
    c.drawString(
        x,
        y,
        "Información provista por servicio de lookup fiscal (versión básica).",
    )
    y -= line_height

    return y

