"""
Exporter per report in formato Markdown.

Genera un file .md leggibile con tabelle, sezioni
e statistiche formattate per ogni colonna del dataset.
"""

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 MarkdownExporter(BaseExporter):
    """Esporta il profilo del dataset in formato Markdown.

    Genera un report strutturato con:
    - Riepilogo generale del dataset
    - Tabella riassuntiva di tutte le colonne
    - Sezioni dettagliate per ogni colonna
    - Eventuali warnings

    Esempio::

        exporter = MarkdownExporter()
        exporter.export(profile, "report.md")
    """

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

        Args:
            profile: Profilo del dataset.
            output_path: Percorso del file .md 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 Markdown come stringa.

        Args:
            profile: Profilo del dataset.

        Returns:
            Stringa contenente il report completo in Markdown.
        """
        lines: list[str] = []

        # Header
        lines.append("# 📊 Report DataProfiler")
        lines.append("")
        lines.append(f"**File:** `{profile.filename}`  ")
        lines.append(f"**Dimensione:** {format_bytes(profile.file_size_bytes)}  ")
        lines.append(f"**Righe:** {profile.row_count:,}  ")
        lines.append(f"**Colonne:** {profile.column_count}  ")
        lines.append(f"**Completezza:** {profile.overall_completeness:.1f}%  ")
        lines.append(f"**Generato il:** {profile.created_at:%Y-%m-%d %H:%M}  ")
        lines.append("")

        # Warnings
        if profile.warnings:
            lines.append("## ⚠️ Avvisi")
            lines.append("")
            for w in profile.warnings:
                lines.append(f"- {w}")
            lines.append("")

        # Tabella riepilogativa
        lines.append("## Riepilogo colonne")
        lines.append("")
        lines.append("| Colonna | Tipo | Completezza | Valori unici | Mancanti |")
        lines.append("|---------|------|-------------|--------------|----------|")
        for col in profile.columns:
            lines.append(
                f"| {col.name} | {col.dtype.value} | "
                f"{col.completeness:.1f}% | {col.unique_count} | "
                f"{col.missing_count} |"
            )
        lines.append("")

        # Dettaglio per colonna
        lines.append("## Dettaglio colonne")
        for col in profile.columns:
            lines.append("")
            lines.append(f"### 📌 {col.name}")
            lines.append("")
            lines.append(f"- **Tipo:** {col.dtype.value}")
            lines.append(f"- **Valori totali:** {col.total_count:,}")
            lines.append(f"- **Mancanti:** {col.missing_count} ({col.missing_percentage:.1f}%)")
            lines.append(f"- **Unici:** {col.unique_count}")

            if col.dtype == ColumnType.NUMERIC and col.stats:
                s = col.stats
                lines.append("")
                lines.append("| Statistica | Valore |")
                lines.append("|------------|--------|")
                lines.append(f"| Min | {format_number(s['min'])} |")
                lines.append(f"| Max | {format_number(s['max'])} |")
                lines.append(f"| Media | {format_number(s['media'])} |")
                lines.append(f"| Mediana | {format_number(s['mediana'])} |")
                lines.append(f"| Std Dev | {format_number(s['std'])} |")
                lines.append(f"| Q1 (25°) | {format_number(s['q1'])} |")
                lines.append(f"| Q3 (75°) | {format_number(s['q3'])} |")
                if s.get("zeros", 0) > 0:
                    lines.append(f"| Zeri | {s['zeros']} |")
                if s.get("negativi", 0) > 0:
                    lines.append(f"| Negativi | {s['negativi']} |")

            elif col.dtype == ColumnType.TEXT and col.stats:
                s = col.stats
                lines.append(f"- **Lunghezza min:** {s.get('lunghezza_min', '-')}")
                lines.append(f"- **Lunghezza max:** {s.get('lunghezza_max', '-')}")
                lines.append(f"- **Lunghezza media:** {s.get('lunghezza_media', '-')}")
                if s.get("tutti_unici"):
                    lines.append("- ℹ️ Tutti i valori sono unici")
                top5 = s.get("top_5_valori", {})
                if top5:
                    lines.append("")
                    lines.append("**Valori più frequenti:**")
                    lines.append("")
                    lines.append("| Valore | Frequenza |")
                    lines.append("|--------|-----------|")
                    for val, freq in top5.items():
                        lines.append(f"| {val} | {freq} |")

            elif col.dtype == ColumnType.DATETIME and col.stats:
                s = col.stats
                lines.append(f"- **Da:** {s.get('data_min', '-')}")
                lines.append(f"- **A:** {s.get('data_max', '-')}")
                lines.append(f"- **Range:** {s.get('range_giorni', 0)} giorni")
                lines.append(f"- **Formato rilevato:** `{s.get('formato_comune', '-')}`")

            elif col.dtype == ColumnType.BOOLEAN and col.stats:
                s = col.stats
                lines.append(f"- **True:** {s.get('true_count', 0)}")
                lines.append(f"- **False:** {s.get('false_count', 0)}")
                lines.append(f"- **% True:** {s.get('percentuale_true', 0)}%")

        lines.append("")
        lines.append("---")
        lines.append(f"*Report generato da DataProfiler v0.1.0*")
        lines.append("")

        return "\n".join(lines)
