"""Migration report generation (PDF + CSV) for sharing with clients."""
import io
import csv
from datetime import datetime

import requests
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import (SimpleDocTemplate, Paragraph, Spacer, Table,
                                TableStyle, Image)


def _fetch_logo(logo_url, max_height_mm=14):
    """Downloads the site logo for embedding in the PDF header.
    Returns a reportlab Image flowable, or None if unavailable/unsupported
    (never raises — a missing/broken logo shouldn't break report generation)."""
    if not logo_url:
        return None
    try:
        resp = requests.get(logo_url, timeout=8)
        resp.raise_for_status()
        content_type = resp.headers.get("Content-Type", "")
        if "svg" in content_type.lower() or logo_url.lower().endswith(".svg"):
            return None  # SVG needs an extra conversion step we don't carry as a dependency
        img_buf = io.BytesIO(resp.content)
        img = Image(img_buf)
        # Scale proportionally to a fixed header height
        ratio = img.imageWidth / float(img.imageHeight)
        img.drawHeight = max_height_mm * mm
        img.drawWidth = img.drawHeight * ratio
        return img
    except Exception:
        return None


def _fmt_bytes(b):
    b = float(b or 0)
    if b == 0:
        return "0 B"
    units = ["B", "KB", "MB", "GB", "TB"]
    i = 0
    while b >= 1024 and i < len(units) - 1:
        b /= 1024.0
        i += 1
    return f"{b:.2f} {units[i]}" if i else f"{int(b)} {units[i]}"


def _fmt_dt(dt):
    if not dt:
        return "—"
    if isinstance(dt, str):
        return dt
    return dt.strftime("%d %b %Y, %H:%M UTC")


def _duration(m):
    if m.started_at and m.completed_at:
        secs = int((m.completed_at - m.started_at).total_seconds())
        h, rem = divmod(secs, 3600)
        mi, s = divmod(rem, 60)
        parts = []
        if h:
            parts.append(f"{h}h")
        if mi:
            parts.append(f"{mi}m")
        parts.append(f"{s}s")
        return " ".join(parts)
    return "—"


def build_csv(m, folders):
    buf = io.StringIO()
    w = csv.writer(buf)
    w.writerow(["Migration Report"])
    w.writerow(["Name", m.name])
    w.writerow(["Status", m.status])
    w.writerow(["Source", m.source_email])
    w.writerow(["Destination", m.dest_email])
    w.writerow(["Date range", f"{m.date_from.date() if m.date_from else 'all'} to {m.date_to.date() if m.date_to else 'all'}"])
    w.writerow(["Created", _fmt_dt(m.created_at)])
    w.writerow(["Started", _fmt_dt(m.started_at)])
    w.writerow(["Completed", _fmt_dt(m.completed_at)])
    w.writerow(["Duration", _duration(m)])
    w.writerow([])
    w.writerow(["Emails migrated", m.migrated_emails or 0])
    w.writerow(["Emails total", m.total_emails or 0])
    w.writerow(["Emails failed", m.failed_emails or 0])
    w.writerow(["Folders", f"{m.migrated_folders or 0}/{m.total_folders or 0}"])
    w.writerow(["Data transferred", _fmt_bytes(m.bytes_transferred)])
    if m.error:
        w.writerow(["Error", m.error])
    w.writerow([])
    w.writerow(["Folder", "Migrated", "Total", "Status"])
    for f in folders:
        w.writerow([f.name, f.migrated or 0, f.total or 0, f.status])
    return buf.getvalue()


def build_pdf(m, folders, site):
    brand = site.get("brand_color", "#2563EB") if site else "#2563EB"
    site_name = (site.get("site_name") if site else None) or "MailShift"
    logo_url = site.get("logo_url") if site else None
    try:
        brand_c = colors.HexColor(brand)
    except Exception:
        brand_c = colors.HexColor("#2563EB")

    buf = io.BytesIO()
    doc = SimpleDocTemplate(buf, pagesize=A4, topMargin=18 * mm, bottomMargin=16 * mm,
                            leftMargin=16 * mm, rightMargin=16 * mm, title=f"{m.name} — Migration Report")
    styles = getSampleStyleSheet()
    h_style = ParagraphStyle("h", parent=styles["Title"], textColor=brand_c, fontSize=20, spaceAfter=2)
    sub = ParagraphStyle("sub", parent=styles["Normal"], textColor=colors.HexColor("#64748B"), fontSize=9)
    label = ParagraphStyle("lbl", parent=styles["Normal"], textColor=colors.HexColor("#64748B"), fontSize=8)
    val = ParagraphStyle("val", parent=styles["Normal"], fontSize=10)
    story = []

    header_text = [
        Paragraph(f"{site_name}", h_style),
        Paragraph("Email Migration Report", sub),
        Paragraph(f"Generated {datetime.utcnow().strftime('%d %b %Y, %H:%M UTC')}", sub),
    ]
    logo = _fetch_logo(logo_url)
    if logo:
        header = Table([[logo, header_text]], colWidths=[40 * mm, None])
        header.setStyle(TableStyle([
            ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
            ("ALIGN", (0, 0), (0, 0), "LEFT"),
            ("LEFTPADDING", (0, 0), (-1, -1), 0),
            ("RIGHTPADDING", (0, 0), (-1, -1), 0),
        ]))
        story.append(header)
    else:
        story.extend(header_text)
    story.append(Spacer(1, 10 * mm))

    story.append(Paragraph(m.name, ParagraphStyle("mn", parent=styles["Heading2"], fontSize=14)))
    story.append(Paragraph(f"{m.source_email} &rarr; {m.dest_email}", val))
    story.append(Spacer(1, 6 * mm))

    date_range = "All emails"
    if m.date_from or m.date_to:
        date_range = f"{m.date_from.date() if m.date_from else 'beginning'} to {m.date_to.date() if m.date_to else 'now'}"

    info = [
        ["Status", (m.status or "").upper(), "Date range", date_range],
        ["Created", _fmt_dt(m.created_at), "Started", _fmt_dt(m.started_at)],
        ["Completed", _fmt_dt(m.completed_at), "Duration", _duration(m)],
    ]
    t = Table(info, colWidths=[26 * mm, 62 * mm, 26 * mm, 62 * mm])
    t.setStyle(TableStyle([
        ("FONTSIZE", (0, 0), (-1, -1), 9),
        ("TEXTCOLOR", (0, 0), (0, -1), colors.HexColor("#64748B")),
        ("TEXTCOLOR", (2, 0), (2, -1), colors.HexColor("#64748B")),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 6),
        ("LINEBELOW", (0, 0), (-1, -2), 0.4, colors.HexColor("#E2E8F0")),
    ]))
    story.append(t)
    story.append(Spacer(1, 8 * mm))

    # Summary metric cards row
    metrics = [
        ["Emails migrated", "Total emails", "Failed", "Data moved", "Folders"],
        [str(m.migrated_emails or 0), str(m.total_emails or 0), str(m.failed_emails or 0),
         _fmt_bytes(m.bytes_transferred), f"{m.migrated_folders or 0}/{m.total_folders or 0}"],
    ]
    mt = Table(metrics, colWidths=[36 * mm] * 5)
    mt.setStyle(TableStyle([
        ("FONTSIZE", (0, 0), (-1, 0), 7),
        ("FONTSIZE", (0, 1), (-1, 1), 13),
        ("FONTNAME", (0, 1), (-1, 1), "Helvetica-Bold"),
        ("TEXTCOLOR", (0, 0), (-1, 0), colors.HexColor("#64748B")),
        ("TEXTCOLOR", (0, 1), (-1, 1), brand_c),
        ("BACKGROUND", (0, 0), (-1, -1), colors.HexColor("#F8FAFC")),
        ("BOX", (0, 0), (-1, -1), 0.5, colors.HexColor("#E2E8F0")),
        ("INNERGRID", (0, 0), (-1, -1), 0.5, colors.HexColor("#E2E8F0")),
        ("TOPPADDING", (0, 0), (-1, -1), 8),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 8),
        ("ALIGN", (0, 0), (-1, -1), "CENTER"),
    ]))
    story.append(mt)
    story.append(Spacer(1, 8 * mm))

    if m.error:
        story.append(Paragraph(f"<b>Error:</b> {m.error}", ParagraphStyle(
            "err", parent=styles["Normal"], fontSize=9, textColor=colors.HexColor("#DC2626"))))
        story.append(Spacer(1, 6 * mm))

    story.append(Paragraph("Folder breakdown", ParagraphStyle("fh", parent=styles["Heading3"], fontSize=11)))
    story.append(Spacer(1, 2 * mm))
    rows = [["Folder", "Migrated", "Total", "Status"]]
    for f in folders:
        rows.append([f.name, str(f.migrated or 0), str(f.total or 0), f.status or "—"])
    if len(rows) == 1:
        rows.append(["No folder data", "", "", ""])
    ft = Table(rows, colWidths=[92 * mm, 28 * mm, 28 * mm, 28 * mm], repeatRows=1)
    ft.setStyle(TableStyle([
        ("FONTSIZE", (0, 0), (-1, -1), 8),
        ("BACKGROUND", (0, 0), (-1, 0), brand_c),
        ("TEXTCOLOR", (0, 0), (-1, 0), colors.white),
        ("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
        ("ROWBACKGROUNDS", (0, 1), (-1, -1), [colors.white, colors.HexColor("#F8FAFC")]),
        ("LINEBELOW", (0, 0), (-1, -1), 0.3, colors.HexColor("#E2E8F0")),
        ("TOPPADDING", (0, 0), (-1, -1), 5),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 5),
    ]))
    story.append(ft)
    story.append(Spacer(1, 10 * mm))
    story.append(Paragraph(f"Report generated by {site_name}", sub))

    doc.build(story)
    return buf.getvalue()
