"""Genera reportes HTML autocontenidos con CSS inline."""


_HTML_ESCAPES = {
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    '"': "&quot;",
    "'": "&#x27;",
}


def _esc(value: str) -> str:
    for ch, entity in _HTML_ESCAPES.items():
        value = value.replace(ch, entity)
    return value


def _render_table(data: list[dict]) -> str:
    if not data:
        return "<p><em>(sin datos)</em></p>"
    headers = list(data[0].keys())
    rows_html = ""
    for i, row in enumerate(data):
        cls = ' class="zebra"' if i % 2 == 1 else ""
        cells = "".join(f"<td>{_esc(str(row.get(h, '')))}</td>" for h in headers)
        rows_html += f"<tr{cls}>{cells}</tr>\n"
    headers_html = "".join(f"<th>{_esc(h)}</th>" for h in headers)
    return (
        f"<table>\n<thead><tr>{headers_html}</tr></thead>\n"
        f"<tbody>\n{rows_html}</tbody>\n</table>"
    )


def _render_text(data: str) -> str:
    # Markdown basico: **bold** y [text](url)
    import re

    text = _esc(str(data))
    # Bold: **text** (despues de escapar, & no interfiere)
    text = re.sub(r"\*\*(.+?)\*\*", r"<strong>\1</strong>", text)
    # Links: [text](url)
    text = re.sub(r"\[(.+?)\]\((.+?)\)", r'<a href="\2">\1</a>', text)
    return f"<p>{text}</p>"


def _render_kpi(data: list[dict]) -> str:
    cards = ""
    for kpi in data:
        label = _esc(str(kpi.get("label", "")))
        value = _esc(str(kpi.get("value", "")))
        delta = kpi.get("delta")
        delta_html = ""
        if delta is not None:
            delta_str = str(delta)
            if delta_str.startswith("+"):
                delta_html = f'<span class="delta-pos">{_esc(delta_str)}</span>'
            elif delta_str.startswith("-"):
                delta_html = f'<span class="delta-neg">{_esc(delta_str)}</span>'
            else:
                delta_html = f'<span class="delta-neutral">{_esc(delta_str)}</span>'
        cards += (
            f'<div class="kpi-card">'
            f'<div class="kpi-label">{label}</div>'
            f'<div class="kpi-value">{value}</div>'
            f"{delta_html}"
            f"</div>\n"
        )
    return f'<div class="kpi-grid">\n{cards}</div>'


def _render_list(data: list[str]) -> str:
    items = "".join(f"<li>{_esc(str(item))}</li>\n" for item in data)
    return f"<ul>\n{items}</ul>"


_CSS = """
body {
    font-family: sans-serif;
    max-width: 960px;
    margin: 2rem auto;
    padding: 0 1rem;
    color: #222;
    background: #fff;
}
h1 { font-size: 1.8rem; border-bottom: 2px solid #ddd; padding-bottom: .5rem; }
h2 { font-size: 1.3rem; margin-top: 2rem; color: #333; }
table { border-collapse: collapse; width: 100%; margin: 1rem 0; font-size: .95rem; }
th { background: #f0f0f0; text-align: left; padding: .5rem .75rem; border: 1px solid #ddd; }
td { padding: .45rem .75rem; border: 1px solid #ddd; }
tr.zebra { background: #f9f9f9; }
ul { padding-left: 1.5rem; }
li { margin: .3rem 0; }
p { line-height: 1.6; }
a { color: #0066cc; }
.kpi-grid { display: flex; flex-wrap: wrap; gap: 1rem; margin: 1rem 0; }
.kpi-card {
    border: 1px solid #ddd;
    border-radius: 6px;
    padding: 1rem 1.5rem;
    min-width: 140px;
    background: #fafafa;
}
.kpi-label { font-size: .85rem; color: #666; margin-bottom: .25rem; }
.kpi-value { font-size: 1.6rem; font-weight: bold; }
.delta-pos { color: #16a34a; font-size: .9rem; }
.delta-neg { color: #dc2626; font-size: .9rem; }
.delta-neutral { color: #888; font-size: .9rem; }
""".strip()


def generate_html_report(title: str, sections: list[dict]) -> str:
    """Genera un reporte HTML autocontenido con CSS inline.

    Cada seccion es un dict con:
        heading: str — titulo de la seccion
        type: "table" | "text" | "kpi" | "list" — tipo de contenido
        data: contenido segun el tipo:
            table -> list[dict]
            text  -> str (soporta **bold** y [links](url))
            kpi   -> list[{"label": str, "value": str|number, "delta": str|None}]
            list  -> list[str]

    No requiere servidor — todo el CSS va inline en <style>.

    Args:
        title: Titulo del reporte (mostrado en <h1> y <title>).
        sections: Lista de secciones a incluir en el reporte.

    Returns:
        String HTML completo con DOCTYPE.
    """
    sections_html = ""
    for section in sections:
        heading = _esc(str(section.get("heading", "")))
        kind = section.get("type", "text")
        data = section.get("data")

        if kind == "table":
            content = _render_table(data or [])
        elif kind == "kpi":
            content = _render_kpi(data or [])
        elif kind == "list":
            content = _render_list(data or [])
        else:
            content = _render_text(str(data or ""))

        sections_html += f"<section>\n<h2>{heading}</h2>\n{content}\n</section>\n"

    return (
        "<!DOCTYPE html>\n"
        "<html lang='es'>\n"
        "<head>\n"
        "<meta charset='UTF-8'>\n"
        "<meta name='viewport' content='width=device-width, initial-scale=1'>\n"
        f"<title>{_esc(title)}</title>\n"
        f"<style>\n{_CSS}\n</style>\n"
        "</head>\n"
        "<body>\n"
        f"<h1>{_esc(title)}</h1>\n"
        f"{sections_html}"
        "</body>\n"
        "</html>"
    )
