"""
Exporter per report in formato HTML.

Genera un file .html autonomo con CSS inline e un design
pulito e professionale, visualizzabile in qualsiasi browser.
"""

from .base import BaseExporter
from dataprofiler.models.dataset_profile import DatasetProfile
from dataprofiler.models.column_profile import ColumnType
from dataprofiler.utils import format_bytes, format_number
from dataprofiler.exceptions import ExportError


class HtmlExporter(BaseExporter):
    """Esporta il profilo del dataset in formato HTML.

    Genera un file HTML completo con CSS inline, leggibile
    in qualsiasi browser senza dipendenze esterne.

    Esempio::

        exporter = HtmlExporter()
        exporter.export(profile, "report.html")
    """

    def export(self, profile: DatasetProfile, output_path: str) -> None:
        """Scrive il report HTML su file.

        Args:
            profile: Profilo del dataset.
            output_path: Percorso del file .html da creare.

        Raises:
            ExportError: Se la scrittura del file fallisce.
        """
        try:
            content = self.to_string(profile)
            with open(output_path, "w", encoding="utf-8") as f:
                f.write(content)
        except OSError as e:
            raise ExportError(f"Impossibile scrivere il file '{output_path}': {e}")

    def to_string(self, profile: DatasetProfile) -> str:
        """Genera il report HTML come stringa.

        Args:
            profile: Profilo del dataset.

        Returns:
            Stringa HTML completa.
        """
        columns_html = self._build_columns_html(profile)
        warnings_html = self._build_warnings_html(profile)
        summary_table = self._build_summary_table(profile)

        return f"""<!DOCTYPE html>
<html lang="it">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DataProfiler — {profile.filename}</title>
    <style>
        * {{ margin: 0; padding: 0; box-sizing: border-box; }}
        body {{ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
               background: #f4f6fa; color: #1a1a2e; line-height: 1.6; padding: 2rem; }}
        .container {{ max-width: 960px; margin: 0 auto; }}
        h1 {{ color: #1b2a4a; margin-bottom: 0.5rem; }}
        h2 {{ color: #2d5f8a; margin: 2rem 0 1rem; border-bottom: 2px solid #e8ecf1; padding-bottom: 0.5rem; }}
        h3 {{ color: #1b2a4a; margin: 1.5rem 0 0.5rem; }}
        .meta {{ color: #8896aa; margin-bottom: 2rem; }}
        .meta span {{ display: inline-block; margin-right: 1.5rem; }}
        .card {{ background: white; border-radius: 8px; padding: 1.5rem; margin-bottom: 1rem;
                 box-shadow: 0 1px 3px rgba(0,0,0,0.1); }}
        .stat-grid {{ display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1rem; margin: 1rem 0; }}
        .stat-item {{ background: #f4f6fa; padding: 1rem; border-radius: 6px; text-align: center; }}
        .stat-value {{ font-size: 1.8rem; font-weight: 700; color: #2d5f8a; }}
        .stat-label {{ font-size: 0.85rem; color: #8896aa; }}
        table {{ width: 100%; border-collapse: collapse; margin: 1rem 0; }}
        th {{ background: #1b2a4a; color: white; padding: 0.75rem 1rem; text-align: left; font-weight: 600; }}
        td {{ padding: 0.6rem 1rem; border-bottom: 1px solid #e8ecf1; }}
        tr:hover td {{ background: #f4f6fa; }}
        .warning {{ background: #fff8e1; border-left: 4px solid #f7c948; padding: 0.75rem 1rem;
                    margin-bottom: 0.5rem; border-radius: 0 6px 6px 0; }}
        .badge {{ display: inline-block; padding: 0.2rem 0.6rem; border-radius: 12px;
                  font-size: 0.8rem; font-weight: 600; }}
        .badge-numeric {{ background: #e3f2fd; color: #1565c0; }}
        .badge-text {{ background: #e8f5e9; color: #2e7d32; }}
        .badge-datetime {{ background: #fce4ec; color: #c62828; }}
        .badge-boolean {{ background: #f3e5f5; color: #6a1b9a; }}
        .badge-unknown {{ background: #eceff1; color: #546e7a; }}
        .completeness-bar {{ height: 8px; background: #e8ecf1; border-radius: 4px; overflow: hidden; }}
        .completeness-fill {{ height: 100%; border-radius: 4px; }}
        .fill-high {{ background: #27ae60; }}
        .fill-mid {{ background: #f7c948; }}
        .fill-low {{ background: #e74c3c; }}
        footer {{ text-align: center; color: #8896aa; margin-top: 3rem; font-size: 0.85rem; }}
    </style>
</head>
<body>
    <div class="container">
        <h1>📊 Report DataProfiler</h1>
        <div class="meta">
            <span><strong>File:</strong> {profile.filename}</span>
            <span><strong>Dimensione:</strong> {format_bytes(profile.file_size_bytes)}</span>
            <span><strong>Generato:</strong> {profile.created_at:%Y-%m-%d %H:%M}</span>
        </div>

        <div class="stat-grid">
            <div class="stat-item">
                <div class="stat-value">{profile.row_count:,}</div>
                <div class="stat-label">Righe</div>
            </div>
            <div class="stat-item">
                <div class="stat-value">{profile.column_count}</div>
                <div class="stat-label">Colonne</div>
            </div>
            <div class="stat-item">
                <div class="stat-value">{profile.overall_completeness:.1f}%</div>
                <div class="stat-label">Completezza</div>
            </div>
            <div class="stat-item">
                <div class="stat-value">{profile.total_missing}</div>
                <div class="stat-label">Valori mancanti</div>
            </div>
        </div>

        {warnings_html}

        <h2>Riepilogo colonne</h2>
        {summary_table}

        <h2>Dettaglio colonne</h2>
        {columns_html}

        <footer>
            <p>Report generato da DataProfiler v0.1.0</p>
        </footer>
    </div>
</body>
</html>"""

    def _build_warnings_html(self, profile: DatasetProfile) -> str:
        if not profile.warnings:
            return ""
        items = "\n".join(
            f'        <div class="warning">⚠️ {w}</div>' for w in profile.warnings
        )
        return f"""
        <h2>Avvisi</h2>
{items}"""

    def _build_summary_table(self, profile: DatasetProfile) -> str:
        rows = ""
        for col in profile.columns:
            badge_class = f"badge-{col.dtype.value}"
            fill_class = (
                "fill-high" if col.completeness >= 90
                else "fill-mid" if col.completeness >= 50
                else "fill-low"
            )
            rows += f"""
            <tr>
                <td><strong>{col.name}</strong></td>
                <td><span class="badge {badge_class}">{col.dtype.value}</span></td>
                <td>
                    <div class="completeness-bar">
                        <div class="completeness-fill {fill_class}" style="width:{col.completeness:.0f}%"></div>
                    </div>
                    {col.completeness:.1f}%
                </td>
                <td>{col.unique_count}</td>
                <td>{col.missing_count}</td>
            </tr>"""

        return f"""
        <table>
            <thead>
                <tr><th>Colonna</th><th>Tipo</th><th>Completezza</th><th>Unici</th><th>Mancanti</th></tr>
            </thead>
            <tbody>{rows}
            </tbody>
        </table>"""

    def _build_columns_html(self, profile: DatasetProfile) -> str:
        sections = ""
        for col in profile.columns:
            detail = self._column_detail_html(col)
            sections += f"""
        <div class="card">
            <h3>📌 {col.name}</h3>
            <p>Tipo: <span class="badge badge-{col.dtype.value}">{col.dtype.value}</span>
               — {col.total_count:,} valori, {col.missing_count} mancanti ({col.missing_percentage:.1f}%),
               {col.unique_count} unici</p>
            {detail}
        </div>"""
        return sections

    def _column_detail_html(self, col) -> str:
        if col.dtype == ColumnType.NUMERIC and col.stats:
            s = col.stats
            return f"""
            <table>
                <tr><td>Min</td><td>{format_number(s['min'])}</td>
                    <td>Max</td><td>{format_number(s['max'])}</td></tr>
                <tr><td>Media</td><td>{format_number(s['media'])}</td>
                    <td>Mediana</td><td>{format_number(s['mediana'])}</td></tr>
                <tr><td>Std Dev</td><td>{format_number(s['std'])}</td>
                    <td>Q1 / Q3</td><td>{format_number(s['q1'])} / {format_number(s['q3'])}</td></tr>
            </table>"""

        elif col.dtype == ColumnType.TEXT and col.stats:
            s = col.stats
            top5 = s.get("top_5_valori", {})
            top_rows = "".join(
                f"<tr><td>{v}</td><td>{c}</td></tr>" for v, c in top5.items()
            )
            return f"""
            <p>Lunghezza: min {s.get('lunghezza_min', '-')}, max {s.get('lunghezza_max', '-')},
               media {s.get('lunghezza_media', '-')}</p>
            <table><thead><tr><th>Valore</th><th>Frequenza</th></tr></thead>
            <tbody>{top_rows}</tbody></table>"""

        elif col.dtype == ColumnType.DATETIME and col.stats:
            s = col.stats
            return f"""
            <p>Da <strong>{s.get('data_min', '-')}</strong> a <strong>{s.get('data_max', '-')}</strong>
               ({s.get('range_giorni', 0)} giorni)</p>
            <p>Formato: <code>{s.get('formato_comune', '-')}</code></p>"""

        elif col.dtype == ColumnType.BOOLEAN and col.stats:
            s = col.stats
            return f"""
            <p>True: {s.get('true_count', 0)} — False: {s.get('false_count', 0)}
               — {s.get('percentuale_true', 0)}% True</p>"""

        return ""
