"""
Python 108 — Certificate Generator
Generates a styled PDF completion certificate using ReportLab.
"""
import io
import hashlib
from datetime import date
from reportlab.lib.pagesizes import A4, landscape
from reportlab.lib.units import mm
from reportlab.lib.colors import HexColor, white, black
from reportlab.pdfgen.canvas import Canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.lib.utils import ImageReader


# ── Colour palette ───────────────────────────────────────────────
PURPLE      = HexColor("#7F77DD")
PURPLE_DK   = HexColor("#3C3489")
PURPLE_LT   = HexColor("#EEEDFE")
TEAL        = HexColor("#1D9E75")
AMBER       = HexColor("#EF9F27")
DARK        = HexColor("#1A1833")
GREY        = HexColor("#5B5780")
LIGHT_GREY  = HexColor("#E2E0F0")
BG          = HexColor("#F8F7FC")


def _cert_number(username: str, completion_date: str) -> str:
    """Generate a deterministic certificate number."""
    raw = f"py108-{username}-{completion_date}"
    h   = hashlib.sha256(raw.encode()).hexdigest()[:8].upper()
    return f"PY108-{h}"


def generate_certificate(username: str, completion_date: str = None) -> bytes:
    """
    Generate a PDF certificate and return as bytes.
    completion_date: ISO string 'YYYY-MM-DD' or None (uses today).
    """
    if not completion_date:
        completion_date = date.today().isoformat()

    cert_no = _cert_number(username, completion_date)

    # Format date nicely
    try:
        y, m, d = completion_date.split("-")
        months  = ["","January","February","March","April","May","June",
                   "July","August","September","October","November","December"]
        nice_date = f"{int(d)} {months[int(m)]} {y}"
    except Exception:
        nice_date = completion_date

    # Canvas — A4 landscape
    buf    = io.BytesIO()
    W, H   = landscape(A4)   # ~841 × 595 pts
    c      = Canvas(buf, pagesize=landscape(A4))

    # ── Background ──────────────────────────────────────────────
    c.setFillColor(BG)
    c.rect(0, 0, W, H, fill=1, stroke=0)

    # Decorative border — outer
    c.setStrokeColor(PURPLE)
    c.setLineWidth(6)
    c.rect(14, 14, W-28, H-28, fill=0, stroke=1)

    # Decorative border — inner
    c.setStrokeColor(PURPLE_LT)
    c.setLineWidth(2)
    c.rect(22, 22, W-44, H-44, fill=0, stroke=1)

    # Corner accents
    for (x, y) in [(14, 14), (W-14, 14), (14, H-14), (W-14, H-14)]:
        c.setFillColor(PURPLE)
        c.circle(x, y, 7, fill=1, stroke=0)

    # ── Top purple header band ───────────────────────────────────
    c.setFillColor(PURPLE_DK)
    c.rect(0, H-90, W, 90, fill=1, stroke=0)

    # Snake emoji area (left)
    c.setFillColor(white)
    c.setFont("Helvetica-Bold", 42)
    c.drawString(36, H-68, "🐍")

    # Header title
    c.setFillColor(white)
    c.setFont("Helvetica-Bold", 28)
    c.drawCentredString(W/2, H-52, "PYTHON 108")
    c.setFont("Helvetica", 13)
    c.setFillColor(PURPLE_LT)
    c.drawCentredString(W/2, H-72, "Complete Python Programming Curriculum")

    # Cert number top-right
    c.setFont("Helvetica", 9)
    c.setFillColor(PURPLE_LT)
    c.drawRightString(W-36, H-40, f"Certificate No. {cert_no}")
    c.drawRightString(W-36, H-56, f"Issued: {nice_date}")

    # ── Certificate of Completion text ───────────────────────────
    c.setFillColor(GREY)
    c.setFont("Helvetica", 13)
    c.drawCentredString(W/2, H-125, "CERTIFICATE OF COMPLETION")

    # Decorative line under subtitle
    c.setStrokeColor(AMBER)
    c.setLineWidth(2)
    c.line(W/2 - 100, H-132, W/2 + 100, H-132)

    # "This is to certify that"
    c.setFillColor(GREY)
    c.setFont("Helvetica", 14)
    c.drawCentredString(W/2, H-162, "This is to certify that")

    # Student name — large and prominent
    c.setFillColor(DARK)
    c.setFont("Helvetica-Bold", 42)
    c.drawCentredString(W/2, H-215, username)

    # Underline for name
    name_w = c.stringWidth(username, "Helvetica-Bold", 42)
    c.setStrokeColor(PURPLE)
    c.setLineWidth(1.5)
    c.line(W/2 - name_w/2, H-222, W/2 + name_w/2, H-222)

    # "has successfully completed"
    c.setFillColor(GREY)
    c.setFont("Helvetica", 14)
    c.drawCentredString(W/2, H-248, "has successfully completed")

    # Course name
    c.setFillColor(PURPLE_DK)
    c.setFont("Helvetica-Bold", 20)
    c.drawCentredString(W/2, H-278, "Python 108 — Complete Python Programming Course")

    # Course description
    c.setFillColor(GREY)
    c.setFont("Helvetica", 12)
    c.drawCentredString(W/2, H-302,
        "comprising 108 programs, 108 exercises, 12 module quizzes")
    c.drawCentredString(W/2, H-318,
        "covering Getting Started through Capstone Projects")

    # Completion date
    c.setFillColor(DARK)
    c.setFont("Helvetica-Bold", 13)
    c.drawCentredString(W/2, H-348, f"Completed on  {nice_date}")

    # ── Stats bar ────────────────────────────────────────────────
    bar_y  = 80
    bar_h  = 50
    bar_x  = 60
    bar_w  = W - 120
    c.setFillColor(PURPLE_DK)
    c.roundRect(bar_x, bar_y, bar_w, bar_h, 8, fill=1, stroke=0)

    stats = [
        ("108", "Programs"),
        ("108", "Exercises"),
        ("12",  "Modules"),
        ("120", "Quiz Questions"),
    ]
    col_w = bar_w / len(stats)
    for i, (val, lbl) in enumerate(stats):
        cx = bar_x + col_w * i + col_w / 2
        c.setFillColor(AMBER)
        c.setFont("Helvetica-Bold", 16)
        c.drawCentredString(cx, bar_y + 30, val)
        c.setFillColor(PURPLE_LT)
        c.setFont("Helvetica", 9)
        c.drawCentredString(cx, bar_y + 14, lbl)
        # Divider
        if i < len(stats) - 1:
            c.setStrokeColor(HexColor("#5a5280"))
            c.setLineWidth(0.5)
            c.line(bar_x + col_w*(i+1), bar_y+8, bar_x+col_w*(i+1), bar_y+bar_h-8)

    # ── Footer ───────────────────────────────────────────────────
    c.setFillColor(GREY)
    c.setFont("Helvetica", 8)
    c.drawCentredString(W/2, 50,
        "This certificate is awarded for the completion of the Python 108 learning curriculum.")
    c.drawCentredString(W/2, 38, f"Verify at: python108.local/certificate/{username}")

    c.save()
    return buf.getvalue()
