"""Generador de PDF para location_agent.

Usa reportlab para generar PDF profesional.
Guarda en: analyses/location_reports/<fecha>_<dirección>.pdf
"""

from __future__ import annotations

import re
from datetime import datetime
from pathlib import Path

_PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent
PDF_DIR = _PROJECT_ROOT / "analyses" / "location_reports"


def export_pdf(report: dict) -> Path:
    """Genera el PDF del reporte. Devuelve la ruta del archivo."""
    try:
        from reportlab.lib.pagesizes import letter
        from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
        from reportlab.lib.units import inch
        from reportlab.lib import colors
        from reportlab.platypus import (
            SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
            HRFlowable, PageBreak,
        )
        from reportlab.lib.enums import TA_CENTER, TA_LEFT
    except ImportError:
        raise ImportError("Instalar reportlab: pip install reportlab")

    PDF_DIR.mkdir(parents=True, exist_ok=True)

    # Nombre del archivo
    safe_addr = re.sub(r"[^\w\s-]", "", report.get("address", "report"))[:60]
    safe_addr = re.sub(r"\s+", "_", safe_addr.strip())
    date_str = datetime.now().strftime("%Y%m%d_%H%M%S")
    filename = PDF_DIR / f"{date_str}_{safe_addr}.pdf"

    doc = SimpleDocTemplate(
        str(filename),
        pagesize=letter,
        rightMargin=0.75 * inch,
        leftMargin=0.75 * inch,
        topMargin=0.75 * inch,
        bottomMargin=0.75 * inch,
    )

    styles = getSampleStyleSheet()

    # Estilos personalizados
    title_style = ParagraphStyle("ARTitle", parent=styles["Title"],
                                  fontSize=20, textColor=colors.HexColor("#1a2744"),
                                  spaceAfter=6)
    h1_style = ParagraphStyle("ARH1", parent=styles["Heading1"],
                               fontSize=14, textColor=colors.HexColor("#1a2744"),
                               spaceBefore=12, spaceAfter=6)
    h2_style = ParagraphStyle("ARH2", parent=styles["Heading2"],
                               fontSize=11, textColor=colors.HexColor("#2d5a8e"))
    body_style = ParagraphStyle("ARBody", parent=styles["Normal"],
                                 fontSize=9, leading=13)
    score_style = ParagraphStyle("ARScore", parent=styles["Normal"],
                                  fontSize=28, textColor=colors.HexColor("#1a2744"),
                                  alignment=TA_CENTER, fontName="Helvetica-Bold")
    caption_style = ParagraphStyle("ARCaption", parent=styles["Normal"],
                                    fontSize=8, textColor=colors.grey)

    story = []

    # --- PORTADA ---
    story.append(Spacer(1, 0.5 * inch))
    story.append(Paragraph("AR-HOUSE", title_style))
    story.append(Paragraph("Location Intelligence Report", styles["Heading2"]))
    story.append(HRFlowable(width="100%", thickness=2, color=colors.HexColor("#1a2744")))
    story.append(Spacer(1, 0.2 * inch))
    story.append(Paragraph(report.get("address", ""), h1_style))
    story.append(Paragraph(f"Análisis: {report.get('analysis_date', '')}", caption_style))
    story.append(Spacer(1, 0.3 * inch))

    # Score general grande
    overall = report.get("overall_score", 0)
    score_color = _score_color(overall)
    story.append(Paragraph(
        f'<font color="{score_color}">{overall}/100</font>',
        score_style,
    ))
    story.append(Paragraph("Score General de Ubicación", styles["Normal"]))
    story.append(Spacer(1, 0.3 * inch))

    # Tabla de scores parciales
    scores = report.get("scores", {})
    score_labels = {
        "crime": "Criminalidad",
        "property": "Mercado Inmobiliario",
        "schools": "Escuelas",
        "amenities": "Amenities",
        "demographics": "Demografía",
        "maritime": "Mercado Marítimo",
        "lifestyle": "Lifestyle Náutico",
    }
    tdata = [["Dimensión", "Score", "Peso"]]
    for k, label in score_labels.items():
        s = scores.get(k, 0)
        w = int({"crime": 20, "property": 20, "schools": 10, "amenities": 15,
                  "demographics": 10, "maritime": 15, "lifestyle": 10}.get(k, 0))
        tdata.append([label, f"{s}/100", f"{w}%"])

    t = Table(tdata, colWidths=[3 * inch, 1.2 * inch, 0.8 * inch])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#1a2744")),
        ("TEXTCOLOR", (0, 0), (-1, 0), colors.white),
        ("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
        ("FONTSIZE", (0, 0), (-1, -1), 9),
        ("ALIGN", (1, 0), (-1, -1), "CENTER"),
        ("ROWBACKGROUNDS", (0, 1), (-1, -1), [colors.white, colors.HexColor("#f5f7fa")]),
        ("GRID", (0, 0), (-1, -1), 0.5, colors.HexColor("#d0d0d0")),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 5),
        ("TOPPADDING", (0, 0), (-1, -1), 5),
    ]))
    story.append(t)
    story.append(PageBreak())

    # --- RESUMEN EJECUTIVO ---
    exec_sec = report.get("sections", {}).get("executive", {})
    story.append(Paragraph("1. Resumen Ejecutivo", h1_style))
    story.append(HRFlowable(width="100%", thickness=1, color=colors.HexColor("#d0d0d0")))

    if exec_sec.get("summary"):
        story.append(Paragraph(exec_sec["summary"], body_style))
    story.append(Spacer(1, 0.15 * inch))

    if exec_sec.get("strengths"):
        story.append(Paragraph("✅ Principales Fortalezas:", h2_style))
        for s in exec_sec["strengths"]:
            story.append(Paragraph(f"• {s}", body_style))

    if exec_sec.get("weaknesses"):
        story.append(Spacer(1, 0.1 * inch))
        story.append(Paragraph("⚠️ Principales Riesgos:", h2_style))
        for w in exec_sec["weaknesses"]:
            story.append(Paragraph(f"• {w}", body_style))
    story.append(PageBreak())

    # --- SECCIONES ---
    section_order = ["crime", "property", "schools", "amenities",
                     "demographics", "maritime", "lifestyle"]
    section_nums = {k: i+2 for i, k in enumerate(section_order)}

    for key in section_order:
        sec = report.get("sections", {}).get(key, {})
        num = section_nums[key]
        score_val = sec.get("score", 0)
        title = sec.get("title", key.title())

        story.append(Paragraph(f"{num}. {title}", h1_style))
        story.append(HRFlowable(width="100%", thickness=1, color=colors.HexColor("#d0d0d0")))

        sc = sec.get("score")
        if sc is not None:
            clr = _score_color(sc)
            story.append(Paragraph(
                f'Score: <font color="{clr}"><b>{sc}/100</b></font>', body_style
            ))

        # Datos clave por sección
        _add_section_data(story, key, sec, body_style, h2_style)

        # Narrativa
        if sec.get("narrative"):
            story.append(Spacer(1, 0.1 * inch))
            story.append(Paragraph("Análisis:", h2_style))
            story.append(Paragraph(sec["narrative"], body_style))

        # Fuentes y errores
        if sec.get("sources"):
            story.append(Spacer(1, 0.05 * inch))
            story.append(Paragraph(
                f"<i>Fuentes: {', '.join(sec['sources'])}</i>", caption_style
            ))
        if sec.get("errors"):
            for err in sec["errors"]:
                story.append(Paragraph(f"<i>⚠ {err}</i>", caption_style))

        story.append(PageBreak())

    # --- PIE DE PÁGINA ---
    story.append(Paragraph("Datos Técnicos", h1_style))
    story.append(Paragraph(
        f"Generado por AR-House Location Intelligence Agent | {report.get('analysis_date', '')} | "
        f"Coordenadas: {report.get('lat', '')}, {report.get('lon', '')}",
        caption_style,
    ))

    doc.build(story)
    return filename


def _score_color(score: int) -> str:
    if score >= 75:
        return "#1a7a1a"  # verde
    elif score >= 50:
        return "#e6a817"  # amarillo
    else:
        return "#b83232"  # rojo


def _add_section_data(story, key: str, sec: dict, body_style, h2_style) -> None:
    """Agrega datos específicos de cada sección al story del PDF."""
    from reportlab.platypus import Paragraph, Spacer, Table, TableStyle
    from reportlab.lib import colors

    story.append(Spacer(1, 0.1 * inch if True else 0))

    if key == "crime":
        total = sec.get("total_crimes_30d", "N/A")
        violent = "Sí" if sec.get("has_violent") else "No"
        story.append(Paragraph(f"Crímenes últimos 30 días: <b>{total}</b>", body_style))
        story.append(Paragraph(f"Presencia de crimen violento: <b>{violent}</b>", body_style))
        types = sec.get("crime_types", {})
        if types:
            story.append(Paragraph("Tipos de crimen:", h2_style))
            for t, count in list(types.items())[:8]:
                story.append(Paragraph(f"• {t}: {count}", body_style))

    elif key == "property":
        fields = [
            ("Precio mediano listado", "median_list_price", "$"),
            ("Precio por sqft", "price_per_sqft", "$/sqft"),
            ("Apreciación 1 año", "appreciation_1y", "%"),
            ("Días en mercado (prom.)", "days_on_market", " días"),
            ("Inventario activo", "inventory", " propiedades"),
            ("Valor tasado condado", "county_assessed_value", "$"),
        ]
        for label, field, unit in fields:
            val = sec.get(field)
            if val is not None:
                if unit == "$":
                    display = f"${val:,}"
                elif unit == "$/sqft":
                    display = f"${val:,}/sqft"
                else:
                    display = f"{val}{unit}"
                story.append(Paragraph(f"{label}: <b>{display}</b>", body_style))

    elif key == "schools":
        avg = sec.get("avg_rating")
        if avg is not None:
            story.append(Paragraph(f"Rating promedio de escuelas: <b>{avg}/10</b>", body_style))
        for level, label in [("best_elementary", "Mejor primaria"),
                              ("best_middle", "Mejor middle school"),
                              ("best_high", "Mejor high school")]:
            school = sec.get(level)
            if school:
                story.append(Paragraph(
                    f"{label}: <b>{school.get('name', 'N/A')}</b> (rating: {school.get('rating', 'N/A')}/10)",
                    body_style,
                ))
        schools = sec.get("schools", [])[:8]
        if schools:
            tdata = [["Escuela", "Nivel", "Rating"]]
            for s in schools:
                tdata.append([s.get("name", "")[:35], s.get("level", ""), str(s.get("rating", "N/A"))])
            t = Table(tdata, colWidths=[3.2 * inch, 1.2 * inch, 0.8 * inch])
            t.setStyle(TableStyle([
                ("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
                ("FONTSIZE", (0, 0), (-1, -1), 8),
                ("GRID", (0, 0), (-1, -1), 0.5, colors.HexColor("#d0d0d0")),
                ("ROWBACKGROUNDS", (0, 1), (-1, -1), [colors.white, colors.HexColor("#f5f7fa")]),
            ]))
            story.append(t)

    elif key == "amenities":
        ws = sec.get("walk_score")
        if ws is not None:
            story.append(Paragraph(f"Walk Score estimado: <b>{ws}/100</b>", body_style))
        nearest = sec.get("nearest", {})
        cat_labels = {
            "supermarket": "Supermercado más cercano",
            "hospital": "Hospital/clínica más cercano",
            "restaurant": "Restaurante más cercano",
            "park": "Parque más cercano",
            "gym": "Gimnasio más cercano",
        }
        for cat, label in cat_labels.items():
            item = nearest.get(cat)
            if item:
                story.append(Paragraph(
                    f"{label}: <b>{item.get('name', 'N/A')}</b> ({item.get('dist_miles', '?')} mi)",
                    body_style,
                ))

    elif key == "demographics":
        income = sec.get("median_household_income")
        if income:
            story.append(Paragraph(f"Ingreso mediano del hogar: <b>${income:,}/año</b>", body_style))
        age = sec.get("median_age")
        if age:
            story.append(Paragraph(f"Edad mediana: <b>{age} años</b>", body_style))
        unemp = sec.get("unemployment_rate")
        if unemp is not None:
            story.append(Paragraph(f"Tasa de desempleo: <b>{unemp}%</b>", body_style))
        edu = sec.get("education_bachelors_pct")
        if edu is not None:
            story.append(Paragraph(f"Con título universitario: <b>{edu}%</b>", body_style))
        pop = sec.get("total_population")
        if pop:
            story.append(Paragraph(f"Población total del área: <b>{pop:,}</b>", body_style))
        eth = sec.get("ethnicity", {})
        if eth:
            story.append(Paragraph("Distribución étnica:", h2_style))
            for k, v in eth.items():
                label = k.replace("_pct", "").replace("_", " ").title()
                story.append(Paragraph(f"• {label}: {v}%", body_style))

    elif key == "maritime":
        shipyards = sec.get("shipyards", [])
        marinas = sec.get("marinas_with_jobs", [])
        employers = sec.get("maritime_employers", [])
        story.append(Paragraph(f"Astilleros encontrados: <b>{len(shipyards)}</b>", body_style))
        story.append(Paragraph(f"Marinas encontradas: <b>{len(marinas)}</b>", body_style))
        story.append(Paragraph(f"Empleadores portuarios: <b>{len(employers)}</b>", body_style))
        bls = sec.get("bls_employment", {})
        if bls.get("latest_employment"):
            story.append(Paragraph(
                f"Empleo marítimo en el estado: <b>{bls['latest_employment']}K empleados</b> "
                f"({bls.get('year', '')})",
                body_style,
            ))

    elif key == "lifestyle":
        nm = sec.get("nearest_marina")
        if nm:
            story.append(Paragraph(
                f"Marina más cercana: <b>{nm.get('name', 'N/A')}</b> ({nm.get('dist_miles', '?')} mi)",
                body_style,
            ))
        nb = sec.get("nearest_beach")
        if nb:
            story.append(Paragraph(
                f"Playa más cercana: <b>{nb.get('name', 'N/A')}</b> ({nb.get('dist_miles', '?')} mi)",
                body_style,
            ))
        story.append(Paragraph(
            f"Acceso oceánico: <b>{'Sí' if sec.get('ocean_access') else 'No'}</b>", body_style
        ))
        story.append(Paragraph(
            f"Vías fluviales cercanas: <b>{'Sí' if sec.get('waterway_nearby') else 'No'}</b>",
            body_style,
        ))
        story.append(Paragraph(
            f"Boat ramps en 10 millas: <b>{len(sec.get('boat_ramps', []))}</b>", body_style
        ))

    from reportlab.lib.units import inch
    story.append(Spacer(1, 0.1 * inch))
