from __future__ import annotations

from io import BytesIO

from reportlab.lib import colors
from reportlab.lib.enums import TA_RIGHT
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
from reportlab.lib.units import inch
from reportlab.platypus import Paragraph, SimpleDocTemplate, Spacer, Table, TableStyle

from app.models import Client, CompanySetting, Event, Invoice
from app.pdf_branding import build_pdf_header_table
from app.quotation_pdf import GPAY_NAME_DEFAULT, PAYMENT_NOTE_DEFAULT, _amount_in_words, _fmt_inr
from app.utils import money


def build_invoice_pdf(
    *,
    invoice: Invoice,
    client: Client | None,
    event: Event | None,
    company: CompanySetting | None,
) -> bytes:
    buffer = BytesIO()
    doc = SimpleDocTemplate(
        buffer,
        pagesize=A4,
        leftMargin=0.55 * inch,
        rightMargin=0.55 * inch,
        topMargin=0.45 * inch,
        bottomMargin=0.45 * inch,
    )
    styles = getSampleStyleSheet()
    normal = ParagraphStyle("NormalSmall", parent=styles["Normal"], fontSize=9, leading=12)
    bold = ParagraphStyle("BoldSmall", parent=normal, fontName="Helvetica-Bold")
    right = ParagraphStyle("Right", parent=normal, alignment=TA_RIGHT)
    title = ParagraphStyle("Title", parent=bold, fontSize=14, textColor=colors.HexColor("#A42FD8"))
    italic_blue = ParagraphStyle("ItalicBlue", parent=normal, fontName="Helvetica-BoldOblique", textColor=colors.HexColor("#123F9A"))

    story: list = []

    story.extend([
        build_pdf_header_table(company=company, normal_style=normal, right_style=right),
        Spacer(1, 0.15 * inch),
    ])
    story.append(Paragraph("TAX INVOICE", title))
    story.append(Spacer(1, 0.12 * inch))

    invoice_date = invoice.invoice_date.strftime("%d/%m/%Y")
    due_date = invoice.due_date.strftime("%d/%m/%Y") if invoice.due_date else "-"
    meta = Table(
        [[
            Paragraph(f"<b>Invoice No:</b> {invoice.invoice_number}<br/><b>Date:</b> {invoice_date}", normal),
            Paragraph(f"<b>Due Date:</b> {due_date}<br/><b>Status:</b> {invoice.status}", right),
        ]],
        colWidths=[4.3 * inch, 2.3 * inch],
    )
    meta.setStyle(TableStyle([("LINEBELOW", (0, 0), (-1, 0), 1, colors.black)]))
    story.extend([meta, Spacer(1, 0.12 * inch)])

    client_label = (client.company_name or client.name if client else None) or "Customer"
    client_lines = [f"To,<br/><b>{client_label}</b>"]
    if client and client.phone:
        client_lines.append(f"Phone: {client.phone}")
    if client and client.email:
        client_lines.append(f"Email: {client.email}")
    if event:
        client_lines.append(f"Event: {event.name}")
        client_lines.append(f"Event date: {event.event_date.strftime('%d/%m/%Y')}")
    story.append(Paragraph("<br/>".join(client_lines), normal))
    story.append(Spacer(1, 0.12 * inch))

    items = list(invoice.items or [])
    subtotal = money(invoice.subtotal)
    discount = money(invoice.discount)
    grand_total = money(invoice.final_amount)
    paid = money(invoice.amount_paid)
    balance = money(invoice.balance_amount)

    table_data = [["Sl. No", "Particulars", "Qty", "Rate", "Amount"]]
    for index, item in enumerate(items, start=1):
        table_data.append([
            str(index),
            Paragraph(item.name.upper(), normal),
            str(item.quantity),
            _fmt_inr(item.unit_price),
            _fmt_inr(item.amount),
        ])

    table_data.extend([
        ["", "", "", "SUBTOTAL", _fmt_inr(subtotal)],
        ["", "", "", "DISCOUNT", _fmt_inr(discount)],
        ["", "", "", "GRAND TOTAL", _fmt_inr(grand_total)],
        ["", "", "", "AMOUNT PAID", _fmt_inr(paid)],
        ["", "", "", "BALANCE DUE", _fmt_inr(balance)],
        [
            Paragraph("<b><i>Amount in Words</i></b>", normal),
            Paragraph(f"<b><i>{_amount_in_words(grand_total)}</i></b>", italic_blue),
            "",
            "",
            "",
        ],
    ])

    table = Table(table_data, colWidths=[0.5 * inch, 2.85 * inch, 0.55 * inch, 1.15 * inch, 1.15 * inch], repeatRows=1)
    table.setStyle(
        TableStyle(
            [
                ("GRID", (0, 0), (-1, len(table_data) - 2), 0.6, colors.black),
                ("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#F3F3F3")),
                ("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
                ("FONTSIZE", (0, 0), (-1, -1), 9),
                ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
                ("ALIGN", (0, 0), (0, -1), "CENTER"),
                ("ALIGN", (2, 0), (2, -1), "CENTER"),
                ("ALIGN", (3, 0), (-1, -1), "RIGHT"),
                ("SPAN", (0, -1), (2, -1)),
                ("SPAN", (3, -1), (-1, -1)),
                ("FONTNAME", (3, -6), (3, -2), "Helvetica-Bold"),
                ("FONTNAME", (4, -6), (4, -2), "Helvetica-Bold"),
            ]
        )
    )
    story.extend([table, Spacer(1, 0.2 * inch)])

    gpay_no = (company.phone if company and company.phone else None) or "9043717464"
    payment = Table(
        [[
            Paragraph(
                "<i>Thank you for choosing Selfie Petti. Please pay the balance amount before the due date.</i>",
                normal,
            ),
            Paragraph(
                "<u><b>PAYMENT DETAILS:-</b></u><br/>"
                f"Gpay no- {gpay_no}<br/>"
                f"Gpay name - {GPAY_NAME_DEFAULT}<br/>"
                f"{PAYMENT_NOTE_DEFAULT}",
                right,
            ),
        ]],
        colWidths=[3.8 * inch, 2.8 * inch],
    )
    story.append(payment)

    doc.build(story)
    return buffer.getvalue()
