"""PDF ticket rendering."""
import io
import os
import re
from pathlib import Path

from nexora.config import BASE_DIR
from nexora.core import app
from nexora.utils.helpers import amount_value
from nexora.services.images import static_file_abs
from nexora.services.qualifiers import qualifier_entry_list
from nexora.services.tickets import ticket_details_for_recipient, ticket_member_roster


def build_ticket_pdf(details, settings, ticket_number_override=None, ticket_holder=None):
    """One-page Nexora ticket.

    Solo -> game, nick name, player info, main QR.
    Team -> same header info plus a compact grid where EVERY member gets
            their own unique scannable QR with their name printed under it.
    The ticket_holder/ticket_number_override arguments are kept for email-flow
    compatibility; the generated document is always the complete one-page
    ticket for the whole registration.
    """
    details = dict(details) if details else {}
    settings = dict(settings) if settings else {}
    from reportlab.lib import colors
    from reportlab.lib.pagesizes import A4
    from reportlab.lib.styles import getSampleStyleSheet
    from reportlab.lib.units import mm
    from reportlab.graphics import renderPDF
    from reportlab.graphics.barcode import qr
    from reportlab.graphics.shapes import Drawing
    from reportlab.pdfbase import pdfmetrics
    from reportlab.pdfbase.ttfonts import TTFont
    from reportlab.platypus import Flowable, Image, PageBreak, Paragraph, SimpleDocTemplate, Spacer, Table, TableStyle
    from xml.sax.saxutils import escape

    regular_font = "NexoraTicketRegular"
    bold_font = "NexoraTicketBold"
    if regular_font not in pdfmetrics.getRegisteredFontNames():
        _font_regular = None
        _font_bold = None
        for _dir, _r, _b in [
            (r"C:\Windows\Fonts", "arial.ttf", "arialbd.ttf"),
            (os.path.join(BASE_DIR, "static", "fonts"), "arial.ttf", "arialbd.ttf"),
            (os.path.join(BASE_DIR, "static", "fonts"), "DejaVuSans.ttf", "DejaVuSans-Bold.ttf"),
            ("/usr/share/fonts/truetype/dejavu", "DejaVuSans.ttf", "DejaVuSans-Bold.ttf"),
            ("/usr/share/fonts/truetype/liberation", "LiberationSans-Regular.ttf", "LiberationSans-Bold.ttf"),
            ("/usr/share/fonts", "DejaVuSans.ttf", "DejaVuSans-Bold.ttf"),
        ]:
            _rpath = os.path.join(_dir, _r)
            _bpath = os.path.join(_dir, _b)
            if os.path.isfile(_rpath) and os.path.isfile(_bpath):
                _font_regular = _rpath
                _font_bold = _bpath
                break
        try:
            pdfmetrics.registerFont(TTFont(regular_font, _font_regular))
        except Exception:
            regular_font = "Helvetica"
        try:
            pdfmetrics.registerFont(TTFont(bold_font, _font_bold))
        except Exception:
            bold_font = "Helvetica-Bold"

    def pdf_text(value):
        value = str(value or "").replace("\r", " ").replace("\n", " ")
        value = re.sub(r"[\x00-\x08\x0b\x0c\x0e-\x1f]", "", value)
        return escape(re.sub(r"\s+", " ", value).strip())

    # -- Logo: canonical static asset first (webp flattened via Pillow so the
    # white mark stays intact), uploads copy fallback. Aspect preserved. --
    logo_info = None
    logo_candidates = [
        static_file_abs(settings.get("site_logo", "")),
        static_file_abs("Images/Logo/Nexora Logo.png"),
        static_file_abs("Images/Logo/Nexora Logo.webp"),
        Path(BASE_DIR) / "static" / "uploads" / "Nexora Logo.png",
    ]
    for candidate in logo_candidates:
        try:
            if candidate and os.path.isfile(str(candidate)):
                from PIL import Image as PILImage
                with PILImage.open(str(candidate)) as pil:
                    pil.load()
                    if pil.width > 200 or pil.height > 200:
                        pil.thumbnail((200, 200))
                    buf = io.BytesIO()
                    pil.convert("RGB").save(buf, format="JPEG", quality=75, optimize=True)
                    buf.seek(0)
                logo_info = {"buf": buf, "w": pil.width, "h": pil.height}
                break
        except Exception:
            continue

    ticket_number = re.sub(r"[^A-Za-z0-9-]", "", str(ticket_number_override or details.get("ticket_number", ""))).upper()
    if not ticket_number:
        ticket_number = f"NX-TICKET-{int(details['id']):04d}"

    is_group = (details["entry_type"] or "").lower() == "group"
    roster = ticket_member_roster(details)
    qualifier_sections = qualifier_entry_list(details)
    primary_ticket_number = roster[0]["serial"] if roster else ticket_number
    entry_status = (details.get("entry_status") or "pending").lower()
    # registration_details returns "Under Verification"; normalise back to the raw key
    payment_status = (details["payment_status"] or "unpaid").lower().replace(" ", "_")

    if payment_status == "paid":
        status_text, status_bg = "PAYMENT VERIFIED - VALID FOR ENTRY", colors.HexColor("#13734d")
    elif payment_status == "under_verification":
        status_text, status_bg = "UNDER VERIFICATION - NOT VALID FOR ENTRY", colors.HexColor("#b45309")
    elif payment_status == "partial":
        status_text, status_bg = "PARTIAL PAYMENT - NOT CONFIRMED", colors.HexColor("#b45309")
    elif payment_status == "refunded":
        status_text, status_bg = "PAYMENT REFUNDED - NOT VALID FOR ENTRY", colors.HexColor("#a32132")
    elif payment_status == "cancelled":
        status_text, status_bg = "REGISTRATION CANCELLED - NOT VALID FOR ENTRY", colors.HexColor("#a32132")
    elif payment_status == "rejected":
        status_text, status_bg = "PAYMENT REJECTED - NOT VALID FOR ENTRY", colors.HexColor("#a32132")
    else:
        status_text, status_bg = "UNPAID - NOT VALID FOR ENTRY", colors.HexColor("#a32132")

    class QRFlowable(Flowable):
        def __init__(self, value, size):
            super().__init__()
            self.value = value
            self.width = size
            self.height = size

        def draw(self):
            code = qr.QrCodeWidget(self.value)
            bounds = code.getBounds()
            width = bounds[2] - bounds[0]
            height = bounds[3] - bounds[1]
            drawing = Drawing(self.width, self.height, transform=[self.width / width, 0, 0, self.height / height, 0, 0])
            drawing.add(code)
            renderPDF.draw(drawing, self.canv, 0, 0)

    stream = io.BytesIO()
    doc = SimpleDocTemplate(
        stream,
        pagesize=A4,
        rightMargin=12 * mm,
        leftMargin=12 * mm,
        topMargin=36 * mm,
        bottomMargin=22 * mm,
        title=f"{ticket_number} - {str(details.get('name', '')).strip()}",
    )
    styles = getSampleStyleSheet()
    story = []

    brand_style = styles["Title"].clone("brand")
    brand_style.fontName = bold_font
    brand_style.fontSize = 17
    brand_style.leading = 20
    brand_style.textColor = colors.white
    brand_sub = styles["BodyText"].clone("brand-sub")
    brand_sub.fontName = regular_font
    brand_sub.fontSize = 9
    brand_sub.leading = 11
    brand_sub.textColor = colors.HexColor("#e5e7eb")

    label_style = styles["BodyText"].clone("lbl")
    label_style.fontName = bold_font
    label_style.fontSize = 8.5
    label_style.leading = 11.5
    label_style.textColor = colors.HexColor("#64748b")
    value_style = styles["BodyText"].clone("val")
    value_style.fontName = regular_font
    value_style.fontSize = 9.5
    value_style.leading = 11.5
    value_style.wordWrap = "CJK"
    value_style.textColor = colors.HexColor("#111827")

    big_value = styles["BodyText"].clone("big-val")
    big_value.fontName = bold_font
    big_value.fontSize = 13
    big_value.leading = 16
    big_value.alignment = 1
    big_value.wordWrap = "CJK"
    big_value.textColor = colors.HexColor("#111827")

    name_style = styles["BodyText"].clone("qr-name")
    name_style.fontName = bold_font
    name_style.fontSize = 7.6
    name_style.leading = 9.2
    name_style.alignment = 1
    name_style.wordWrap = "CJK"

    section_style = styles["BodyText"].clone("section")
    section_style.fontName = bold_font
    section_style.fontSize = 9.5
    section_style.leading = 12
    section_style.textColor = colors.white

    status_line = styles["BodyText"].clone("status-line")
    status_line.fontName = bold_font
    status_line.fontSize = 10.5
    status_line.leading = 13
    status_line.alignment = 1
    status_line.textColor = colors.white

    # -- Brand band drawn via canvas on every page (see _draw_page_footer below) --
    # Store logo buffers for canvas drawing; brand band removed from story.
    # Nexora logo PNG bytes for canvas.drawImage
    _nexora_logo_bytes = None
    if logo_info is not None:
        _nexora_logo_bytes = logo_info["buf"].getvalue()
    # Load 4 ticket logos from static/Images/Ticket Logo/
    _ticket_logos = []
    _ticket_logo_dir = os.path.join(app.static_folder, "Images", "Ticket Logo")
    _ticket_logo_order = ["Nexora.jpeg", "dawlance.webp", "govt.jpg", "WHS.jpeg", "genz.webp"]
    try:
        from reportlab.lib.utils import ImageReader as RLImageReader
        from PIL import Image as PILImage
        for _fname in _ticket_logo_order:
            _fpath = os.path.join(_ticket_logo_dir, _fname)
            if os.path.isfile(_fpath):
                try:
                    _pil = PILImage.open(_fpath)
                    if _pil.width > 200 or _pil.height > 200:
                        _pil.thumbnail((200, 200))
                    _pil = _pil.convert("RGBA")
                    _buf = io.BytesIO()
                    _pil.save(_buf, format="PNG", optimize=True)
                    _buf.seek(0)
                    _ticket_logos.append(RLImageReader(_buf))
                except Exception:
                    pass
    except Exception:
        pass
    story.append(Spacer(1, 6))

    # -- Status strip (payment state + check-in warning) --
    if entry_status == "approved":
        entry_chip = "  |  ALREADY ENTERED"
        strip_color = colors.HexColor("#4b5563")
    elif entry_status == "rejected":
        entry_chip = "  |  ENTRY REJECTED"
        strip_color = colors.HexColor("#7f1d1d")
    else:
        entry_chip = ""
        strip_color = status_bg
    status_strip = Table(
        [[Paragraph(pdf_text(status_text + entry_chip).replace("|", "|"), status_line)]],
        colWidths=[186 * mm],
    )
    status_strip.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (-1, -1), strip_color),
        ("TOPPADDING", (0, 0), (-1, -1), 5), ("BOTTOMPADDING", (0, 0), (-1, -1), 5),
        ("LEFTPADDING", (0, 0), (-1, -1), 6), ("RIGHTPADDING", (0, 0), (-1, -1), 6),
    ]))
    story.append(status_strip)
    story.append(Spacer(1, 5))

    # ── Compact info table (no section header, fits beside QR) ──
    def kv_compact(rows):
        data = []
        for label, value in rows:
            data.append([
                Paragraph(pdf_text(label), label_style),
                Paragraph(pdf_text(value), value_style),
            ])
        t = Table(data, colWidths=[34 * mm, 106 * mm])
        t.setStyle(TableStyle([
            ("GRID", (0, 0), (-1, -1), 0.3, colors.HexColor("#dbe2ec")),
            ("BACKGROUND", (0, 0), (0, -1), colors.HexColor("#f4f6fb")),
            ("ROWBACKGROUNDS", (1, 1), (1, -1), [colors.white, colors.HexColor("#fbfdff")]),
            ("VALIGN", (0, 0), (-1, -1), "TOP"),
            ("LEFTPADDING", (0, 0), (-1, -1), 4), ("RIGHTPADDING", (0, 0), (-1, -1), 4),
            ("TOPPADDING", (0, 0), (-1, -1), 2), ("BOTTOMPADDING", (0, 0), (-1, -1), 2),
        ]))
        return t

    nick = details.get("team_name") or ""
    leader_name = details.get("leader_name") or details.get("name") or ""
    team_label = details.get("team_label") or ""
    registration_label = details.get("registration_label") or ""
    team_display_label = registration_label if registration_label else (team_label if team_label else "Team Name")
    player_display_label = registration_label if registration_label else "Player Name"
    info_rows = [
        ("Event Name", settings["event_title"] if "event_title" in settings.keys() else "Nexora Esports Championship"),
        ("Ticket #", primary_ticket_number),
        ("Reg ID", f"NX-{int(details['id']):04d}"),
        ("Game", details["game"]),
    ]

    q_count = int(details.get("qualifier_count", 0) or 0)
    has_qualifier_passes = bool(qualifier_sections)
    total_entries = (
        sum(len(q.get("members", [])) for q in qualifier_sections)
        if has_qualifier_passes
        else len(roster)
    )

    info_rows.append(("Total Passes (#)", f"{total_entries} Ticket(s) in this PDF"))
    info_rows.append(("Entry Type", f"{details['entry_type'].title()} - {len(roster)} Player(s)"))
    if q_count > 0:
        info_rows.append(("Qualifiers Applied", f"{q_count} Qualifier(s)"))
        info_rows.append(("Ticket Mode", "Qualifier passes only"))
    else:
        info_rows.append(("Ticket Mode", "Game/member passes"))
        
    if is_group:
        info_rows.append((team_display_label, details.get("team_name") or nick))
        info_rows.append(("Group Leader", leader_name))
    else:
        if nick:
            info_rows.append((player_display_label or "Player Name", nick))
        info_rows.append(("Full Name", details.get("name") or ""))
    info_rows.append(("Email", details.get("email")))
    info_rows.append(("Phone", details.get("phone")))
    info_rows.append(("CNIC", details.get("cnic")))
    
    info_rows.append(("Payment Status", "PAID" if payment_status == "paid" else ("UNDER VERIFICATION" if payment_status == "under_verification" else "UNPAID")))
    snap_orig = details.get("snapshot_original") or "Rs. 0"
    snap_disc = details.get("snapshot_discount") or "Rs. 0"
    info_rows.append(("Original Fee", snap_orig))
    if snap_disc and snap_disc != "Rs. 0":
        stype = details.get("snapshot_type")
        sval = details.get("snapshot_val")
        label_disc = "Discount Applied"
        if sval and sval != "0":
            if stype == "percentage":
                label_disc += f" ({sval}%)"
            else:
                label_disc += " (Fixed)"
        info_rows.append((label_disc, snap_disc))
    
    qp = details.get("qualifier_pricing")
    if qp and qp.get("count") and not qp.get("is_historical"):
        qp_str = ""
        for item in qp.get("items", []):
            qp_str += f"{item['name']}: {item['original_fee']}"
            if qp.get("discount_active"):
                qp_str += f" - {item['discount_fee']} ({qp.get('discount_pct')}% off)"
            qp_str += f" = {item['final_fee']}\n"
        qp_str += f"Total: {qp.get('total_original_fee')}"
        if qp.get("discount_active"):
            qp_str += f" - {qp.get('total_discount_fee')}"
        qp_str += f" = {qp.get('total_fee')}"
        info_rows.append(("Qualifier Pricing", qp_str.strip()))
        
    info_rows.append(("Total Payable", details.get("total_payable") or "Rs. 0"))
    info_rows.append(("Amount Paid", details.get("amount_paid") or "Rs. 0"))

    leader_entry = roster[0]
    all_members = roster

    # ── SMALL QR + LABEL styles ──
    qr_main_size = 36 * mm
    qr_small_size = 20 * mm

    mini_lbl = styles["BodyText"].clone("minilbl")
    mini_lbl.fontName = bold_font
    mini_lbl.fontSize = 5.8
    mini_lbl.leading = 7.2
    mini_lbl.alignment = 1
    mini_lbl.textColor = colors.white

    mini_name = styles["BodyText"].clone("mininm")
    mini_name.fontName = bold_font
    mini_name.fontSize = 6.2
    mini_name.leading = 7.5
    mini_name.alignment = 1
    mini_name.textColor = colors.HexColor("#111827")

    mini_detail = styles["BodyText"].clone("minidt")
    mini_detail.fontName = regular_font
    mini_detail.fontSize = 5.5
    mini_detail.leading = 6.8
    mini_detail.alignment = 1
    mini_detail.textColor = colors.HexColor("#475569")

    q_status_mini = styles["BodyText"].clone("qstmini")
    q_status_mini.fontName = bold_font
    q_status_mini.fontSize = 5.2
    q_status_mini.leading = 6.5
    q_status_mini.alignment = 1

    def card_status_label(member_status):
        ms = (member_status or "pending").lower()
        if ms == "approved":
            return "CHECKED IN", "#16a34a"
        if ms == "rejected":
            return "REJECTED", "#dc2626"
        return "PENDING", "#b45309"

    def build_mini_card(label_text, qr_value, qr_size, name_text, detail_lines, status_text, status_color, band_color):
        cells_label = [[Paragraph(pdf_text(label_text), mini_lbl)]]
        cells_qr = [[QRFlowable(str(qr_value), qr_size)]]
        inner_items = []
        inner_items.append(Paragraph(pdf_text(name_text), mini_name))
        for dl in detail_lines:
            inner_items.append(Paragraph(pdf_text(dl), mini_detail))
        st_p = Paragraph(status_text, q_status_mini)
        st_p.style.textColor = colors.HexColor(status_color)
        inner_items.append(st_p)
        cells_info = [inner_items]
        card_tbl = Table(
            [[cells_label[0]], [cells_qr[0]], [cells_info[0]]],
            colWidths=[None],
        )
        card_tbl.setStyle(TableStyle([
            ("BACKGROUND", (0, 0), (0, 0), band_color),
            ("ALIGN", (0, 0), (-1, -1), "CENTER"),
            ("VALIGN", (0, 0), (-1, -1), "TOP"),
            ("LEFTPADDING", (0, 0), (-1, -1), 2),
            ("RIGHTPADDING", (0, 0), (-1, -1), 2),
            ("TOPPADDING", (0, 0), (-1, -1), 2),
            ("BOTTOMPADDING", (0, 0), (-1, -1), 2),
            ("BOX", (0, 0), (-1, -1), 0.3, colors.HexColor("#d1d5db")),
        ]))
        return card_tbl

    # ── MAIN LAYOUT: QR (left) + Info (right) ──
    main_m = roster[0]
    info_panel = kv_compact(info_rows)

    main_qr = QRFlowable(f"NXT:{main_m['token']}", qr_main_size)
    top_row = Table(
        [[main_qr, info_panel]],
        colWidths=[qr_main_size + 6 * mm, 142 * mm],
    )

    top_row.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(top_row)
    story.append(Spacer(1, 5))

    # ── TEAM MEMBER QRs ──
    if not has_qualifier_passes and is_group and len(roster) > 1:
        game_venue = details.get("game_venue") or ""
        game_date = details.get("game_date") or ""
        game_time = details.get("game_time") or ""
        game_schedule = f"{game_date}" + (f" {game_time}" if game_time else "") if game_date else ""

        hdr_text = f"<b>TEAM MEMBERS &mdash; {details.get('game', '').upper()}</b>"
        hdr = Table(
            [[Paragraph(hdr_text, section_style)]],
            colWidths=[186 * mm],
        )
        hdr.setStyle(TableStyle([
            ("BACKGROUND", (0, 0), (-1, -1), colors.HexColor("#1e3a8a")),
            ("TOPPADDING", (0, 0), (-1, -1), 2), ("BOTTOMPADDING", (0, 0), (-1, -1), 2),
            ("LEFTPADDING", (0, 0), (-1, -1), 5),
        ]))
        story.append(hdr)
        story.append(Spacer(1, 2))

        m_cards = []
        for m in roster[1:]:
            stxt, scol = card_status_label(m.get("status"))
            detail_lines = []
            if m.get("phone"): detail_lines.append(f"Ph: {m['phone']}")
            if m.get("email"): detail_lines.append(m['email'])
            if m.get("cnic"): detail_lines.append(f"CNIC: {m['cnic']}")
            if m.get("ticket_id"): detail_lines.append(f"ID: {m['ticket_id']}")
            if game_schedule: detail_lines.append(f"Date: {game_schedule}")
            if game_venue and game_venue != "TBD": detail_lines.append(f"Venue: {game_venue}")
            m_cards.append(build_mini_card(
                f"Member {m.get('number') or ''}".strip(), f"NXT:{m.get('token')}", qr_small_size,
                m.get("name") or "", detail_lines, stxt, scol, colors.HexColor("#1e3a8a")
            ))

        if m_cards:
            gap_m = 2 * mm
            total_w = 186 * mm
            for i in range(0, len(m_cards), 4):
                chunk = m_cards[i:i+4]
                cw = min(43 * mm, total_w / len(chunk))
                row_tbl = Table([chunk], colWidths=[cw] * len(chunk))
                row_tbl.setStyle(TableStyle([
                    ("VALIGN", (0, 0), (-1, -1), "TOP"),
                    ("LEFTPADDING", (0, 0), (-1, -1), 0),
                    ("RIGHTPADDING", (0, 0), (-1, -1), gap_m),
                    ("TOPPADDING", (0, 0), (-1, -1), 0),
                    ("BOTTOMPADDING", (0, 0), (-1, -1), 0),
                ]))
                story.append(row_tbl)
                story.append(Spacer(1, 1 * mm))
            story.append(Spacer(1, 4 * mm))

    # ── QUALIFIER QRS (grouped layout: stacked horizontally like team members) ──
    if has_qualifier_passes:
        gap_m = 2 * mm
        total_w = 186 * mm
        
        hdr_text = f"<b>QUALIFIER PASSES &mdash; {details.get('game', '').upper()}</b>"
        q_hdr = Table([[Paragraph(hdr_text, section_style)]], colWidths=[186 * mm])
        q_hdr.setStyle(TableStyle([
            ("BACKGROUND", (0, 0), (-1, -1), colors.HexColor("#86192a")),
            ("TOPPADDING", (0, 0), (-1, -1), 2), ("BOTTOMPADDING", (0, 0), (-1, -1), 2),
            ("LEFTPADDING", (0, 0), (-1, -1), 5),
        ]))
        story.append(q_hdr)
        story.append(Spacer(1, 2 * mm))
        
        q_cards = []
        for section in qualifier_sections:
            for m in section["members"]:
                stxt, scol = card_status_label(m.get("entry_status"))
                detail_lines = []
                if m.get("player_email"): detail_lines.append(m['player_email'])
                if m.get("player_phone"): detail_lines.append(f"Ph: {m['player_phone']}")
                if m.get("player_cnic"): detail_lines.append(f"CNIC: {m['player_cnic']}")
                if m.get("ticket_serial"): detail_lines.append(f"ID: {m['ticket_serial']}")
                if section.get("qualifier_date"): detail_lines.append(f"Date: {section['qualifier_date']}")
                if section.get("qualifier_time"): detail_lines.append(f"Time: {section['qualifier_time']}")
                _q_venue = section.get("venue") or ""
                if _q_venue and _q_venue != "TBD": detail_lines.append(f"Venue: {_q_venue}")
                
                card_lbl = f"Q{section['qualifier_number']}"
                if is_group:
                    card_lbl += f" - {m.get('role', 'Member')}"
                else:
                    card_lbl += " - Player"
                    
                q_cards.append(build_mini_card(
                    card_lbl, f"NQ:{m['ticket_token']}", qr_small_size,
                    m.get("player_name") or "", detail_lines, stxt, scol, colors.HexColor("#86192a")
                ))
                
        if q_cards:
            for i in range(0, len(q_cards), 4):
                chunk = q_cards[i:i+4]
                cw = min(43 * mm, total_w / len(chunk))
                row_tbl = Table([chunk], colWidths=[cw] * len(chunk))
                row_tbl.setStyle(TableStyle([
                    ("VALIGN", (0, 0), (-1, -1), "TOP"),
                    ("LEFTPADDING", (0, 0), (-1, -1), 0),
                    ("RIGHTPADDING", (0, 0), (-1, -1), gap_m),
                    ("TOPPADDING", (0, 0), (-1, -1), 0),
                    ("BOTTOMPADDING", (0, 0), (-1, -1), 0),
                ]))
                story.append(row_tbl)
                story.append(Spacer(1, 1 * mm))
        story.append(Spacer(1, 4 * mm))

    footer_style = styles["BodyText"].clone("footer")
    footer_style.fontName = regular_font
    footer_style.fontSize = 7.8
    footer_style.leading = 10
    footer_style.alignment = 1
    footer_style.textColor = colors.HexColor("#64748b")
    _contact_email = (settings["contact_email"] if settings and "contact_email" in settings.keys() else "").strip() or "nexora.esport.support@gmail.com"
    _footer_text = f"For Help & Support: {_contact_email}  |  Helpline: +92 331 0314962"

    def _draw_page_footer(canvas, doc):
        canvas.saveState()
        page_w, page_h = A4
        margin_lr = 12 * mm
        content_w = page_w - 2 * margin_lr

        # -- Header: Top Logo Strip --
        canvas.setFillColor(colors.HexColor("#0b0d14"))
        canvas.rect(0, A4[1] - 32 * mm, A4[0], 35 * mm, stroke=0, fill=1)
        
        if _ticket_logos:
            try:
                logo_h = 12 * mm
                gap = 6 * mm
                logo_entries = []
                for ir in _ticket_logos:
                    iw, ih = ir.getSize()
                    lw = logo_h * (iw / float(ih or 1))
                    logo_entries.append((ir, lw))
                total_w = sum(lw for _, lw in logo_entries) + gap * (len(logo_entries) - 1)
                start_x = (page_w - total_w) / 2
                logo_y = page_h - margin_lr - logo_h - 2 * mm
                cx = start_x
                for ir, lw in logo_entries:
                    canvas.drawImage(ir, cx, logo_y, width=lw, height=logo_h, preserveAspectRatio=True, mask='auto')
                    cx += lw + gap
            except Exception:
                pass

        # -- Footer --
        canvas.setFillColor(colors.HexColor("#64748b"))
        canvas.setFont(regular_font, 7.5)
        canvas.drawCentredString(page_w / 2, 10 * mm, _footer_text)
        canvas.restoreState()

    story.append(Spacer(1, 4))
    doc.build(story, onFirstPage=_draw_page_footer, onLaterPages=_draw_page_footer)
    raw_pdf = stream.getvalue()
    # Compress PDF using pikepdf if available for smaller file size
    try:
        import pikepdf
        src = pikepdf.open(io.BytesIO(raw_pdf))
        compressed = io.BytesIO()
        src.save(compressed, compress_streams=True, object_stream_mode=pikepdf.ObjectStreamMode.generate)
        src.close()
        return compressed.getvalue()
    except ImportError:
        pass
    except Exception:
        pass
    return raw_pdf
