from __future__ import annotations

from datetime import date
from decimal import Decimal
from io import BytesIO

from num2words import num2words
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, Enquiry, Product, Quotation
from app.pdf_branding import build_pdf_header_table
from app.utils import money

GPAY_NAME_DEFAULT = "Muthu Subramanian"
PAYMENT_NOTE_DEFAULT = "(only for advance payment)"


def _fmt_inr(value) -> str:
    amount = money(value)
    if amount == amount.to_integral_value():
        return f"RS.{int(amount):,}"
    return f"RS.{amount:,.2f}"


def _amount_in_words(value) -> str:
    amount = int(money(value))
    words = num2words(amount, lang="en_IN")
    return f"{words.title()} rupees ONLY"


def quotation_reference(quotation: Quotation, sequence: int) -> str:
    when = quotation.quotation_date or date.today()
    return f"Selfie-{when.year}/{when.month:02d} - {sequence:02d}"


def build_quotation_pdf(
    *,
    quotation: Quotation,
    enquiry: Enquiry,
    client: Client | None,
    company: CompanySetting | None,
    products_by_id: dict[int, Product],
    reference_no: str,
    transport_amount: Decimal = Decimal("0"),
) -> 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)
    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.18 * inch),
    ])

    client_label = (client.company_name or client.name if client else None) or enquiry.client_name
    story.append(Paragraph(f"To,<br/>{client_label}", normal))
    story.append(Spacer(1, 0.08 * inch))
    story.append(Paragraph("Respected Sir,", normal))
    story.append(Spacer(1, 0.08 * inch))

    event_when = enquiry.event_date.strftime("%b %d") if enquiry.event_date else "your event"
    story.append(Paragraph(f"Subject : Event on {event_when} – regarding", bold))
    story.append(Spacer(1, 0.08 * inch))

    quote_date = quotation.quotation_date.strftime("%d/%m/%Y")
    ref_row = Table(
        [[
            Paragraph(f"Reference : Quotation No.: {reference_no}", normal),
            Paragraph(f"Date: {quote_date}", right),
        ]],
        colWidths=[4.3 * inch, 2.3 * inch],
    )
    ref_row.setStyle(TableStyle([("LINEBELOW", (0, 0), (-1, 0), 1, colors.black)]))
    story.extend([ref_row, Spacer(1, 0.1 * inch)])

    company_name = (company.company_name if company else None) or "Selfie petti"
    story.append(Paragraph(f"Greetings from {company_name} Games!", normal))
    story.append(Spacer(1, 0.12 * inch))

    items = list(quotation.items or [])
    subtotal = money(quotation.subtotal)
    transport = money(transport_amount)
    discount = money(quotation.discount)
    total_before_discount = money(subtotal + transport)
    grand_total = money(quotation.final_amount)

    table_data = [["Sl. No", "Particulars", "Per Event (3- 4 hrs )", "Net Amount"]]
    for index, item in enumerate(items, start=1):
        product = products_by_id.get(item.product_id or -1)
        duration = product.service_duration if product and product.service_duration else ""
        particulars = item.name.upper()
        if duration:
            particulars = f"{particulars}<br/><font size='7'>{duration}</font>"
        table_data.append([
            str(index),
            Paragraph(particulars, normal),
            _fmt_inr(item.unit_price),
            "",
        ])

    if items:
        table_data.append(["", "", "", _fmt_inr(subtotal)])

    if transport > 0:
        table_data.append(["", "TRANSPORT", "", _fmt_inr(transport)])

    summary_rows: list[int] = []
    table_data.append(["", "TOTAL", "", _fmt_inr(total_before_discount)])
    summary_rows.append(len(table_data) - 1)
    if discount > 0:
        table_data.append(["", "DISCOUNT AMOUNT", "", _fmt_inr(discount)])
        summary_rows.append(len(table_data) - 1)
    table_data.append(["", "GRAND TOTAL", "", _fmt_inr(grand_total)])
    summary_rows.append(len(table_data) - 1)
    table_data.append(
        [
            Paragraph("<b><i>Amount in Words</i></b>", normal),
            Paragraph(f"<b><i>{_amount_in_words(grand_total)}</i></b>", italic_blue),
            "",
            "",
        ]
    )

    style_commands = [
        ("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), "RIGHT"),
        ("ALIGN", (3, 0), (3, -1), "RIGHT"),
        ("SPAN", (0, -1), (1, -1)),
        ("SPAN", (2, -1), (3, -1)),
    ]
    for row_index in summary_rows:
        style_commands.append(("FONTNAME", (1, row_index), (1, row_index), "Helvetica-Bold"))
        style_commands.append(("FONTNAME", (3, row_index), (3, row_index), "Helvetica-Bold"))

    table = Table(table_data, colWidths=[0.55 * inch, 3.35 * inch, 1.35 * inch, 1.15 * inch], repeatRows=1)
    table.setStyle(TableStyle(style_commands))
    story.extend([table, Spacer(1, 0.15 * inch)])

    story.append(
        Paragraph(
            "With reference to the above, following are the quote for the Selfie petti Games services for your concern.",
            normal,
        )
    )
    story.append(Spacer(1, 0.08 * inch))
    story.append(
        Paragraph(
            "<i>*This quotation is valid only for this event and this package. Any changes in location, "
            "products, or event date may result in a change in pricing.</i>",
            normal,
        )
    )
    story.append(Spacer(1, 0.25 * inch))

    gpay_no = (company.phone if company and company.phone else None) or "9043717464"
    payment = Table(
        [[
            Paragraph("", 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()
