"""Test per gli exporter (Markdown, JSON, HTML, ExporterFactory)."""

import json
import pytest

from dataprofiler.exporters import (
    ExporterFactory, MarkdownExporter, JsonExporter, HtmlExporter,
)
from dataprofiler.models.dataset_profile import DatasetProfile
from dataprofiler.models.column_profile import ColumnProfile, ColumnType
from dataprofiler.exceptions import UnsupportedFormatError


@pytest.fixture
def sample_profile():
    """Crea un profilo di esempio per i test degli exporter."""
    profile = DatasetProfile(
        filename="test.csv",
        row_count=100,
        column_count=3,
        file_size_bytes=2048,
    )
    profile.columns = [
        ColumnProfile(
            name="eta",
            dtype=ColumnType.NUMERIC,
            total_count=100,
            missing_count=5,
            unique_count=40,
            stats={"min": 18.0, "max": 65.0, "media": 35.2,
                   "mediana": 33.0, "std": 12.5, "q1": 25.0,
                   "q3": 45.0, "somma": 3520.0, "zeros": 0, "negativi": 0},
        ),
        ColumnProfile(
            name="nome",
            dtype=ColumnType.TEXT,
            total_count=100,
            missing_count=0,
            unique_count=95,
            stats={"lunghezza_min": 3, "lunghezza_max": 20,
                   "lunghezza_media": 8.5, "tutti_unici": False,
                   "top_5_valori": {"Marco": 3, "Luca": 2, "Anna": 2,
                                    "Sara": 1, "Giulia": 1},
                   "valori_distinti": 95},
        ),
        ColumnProfile(
            name="data",
            dtype=ColumnType.DATETIME,
            total_count=100,
            missing_count=2,
            unique_count=30,
            stats={"data_min": "2023-01-01", "data_max": "2024-06-30",
                   "range_giorni": 546, "formato_comune": "%Y-%m-%d",
                   "date_distinte": 30},
        ),
    ]
    profile.warnings = ["Colonna 'eta': 5% valori mancanti"]
    return profile


class TestExporterFactory:
    """Test per ExporterFactory (pattern Factory)."""

    def test_create_markdown(self):
        assert isinstance(ExporterFactory.create("md"), MarkdownExporter)

    def test_create_json(self):
        assert isinstance(ExporterFactory.create("json"), JsonExporter)

    def test_create_html(self):
        assert isinstance(ExporterFactory.create("html"), HtmlExporter)

    def test_unsupported_format(self):
        with pytest.raises(UnsupportedFormatError):
            ExporterFactory.create("pdf")

    def test_supported_formats(self):
        formats = ExporterFactory.supported_formats()
        assert "md" in formats
        assert "json" in formats
        assert "html" in formats


class TestMarkdownExporter:
    """Test per MarkdownExporter."""

    def test_to_string(self, sample_profile):
        exporter = MarkdownExporter()
        result = exporter.to_string(sample_profile)
        assert "# 📊 Report DataProfiler" in result
        assert "test.csv" in result
        assert "eta" in result
        assert "nome" in result

    def test_export_creates_file(self, sample_profile, tmp_output):
        path = str(tmp_output / "report.md")
        exporter = MarkdownExporter()
        exporter.export(sample_profile, path)
        assert (tmp_output / "report.md").exists()

    def test_export_contains_stats(self, sample_profile):
        exporter = MarkdownExporter()
        result = exporter.to_string(sample_profile)
        assert "Media" in result
        assert "Mediana" in result

    def test_export_contains_warnings(self, sample_profile):
        exporter = MarkdownExporter()
        result = exporter.to_string(sample_profile)
        assert "Avvisi" in result


class TestJsonExporter:
    """Test per JsonExporter."""

    def test_to_string_is_valid_json(self, sample_profile):
        exporter = JsonExporter()
        result = exporter.to_string(sample_profile)
        data = json.loads(result)
        assert "dataset" in data
        assert "colonne" in data

    def test_export_creates_file(self, sample_profile, tmp_output):
        path = str(tmp_output / "report.json")
        exporter = JsonExporter()
        exporter.export(sample_profile, path)
        assert (tmp_output / "report.json").exists()
        with open(path) as f:
            data = json.load(f)
        assert data["dataset"]["righe"] == 100

    def test_contains_all_columns(self, sample_profile):
        exporter = JsonExporter()
        result = json.loads(exporter.to_string(sample_profile))
        assert len(result["colonne"]) == 3


class TestHtmlExporter:
    """Test per HtmlExporter."""

    def test_to_string_is_html(self, sample_profile):
        exporter = HtmlExporter()
        result = exporter.to_string(sample_profile)
        assert "<!DOCTYPE html>" in result
        assert "DataProfiler" in result

    def test_export_creates_file(self, sample_profile, tmp_output):
        path = str(tmp_output / "report.html")
        exporter = HtmlExporter()
        exporter.export(sample_profile, path)
        assert (tmp_output / "report.html").exists()

    def test_contains_completeness_bars(self, sample_profile):
        exporter = HtmlExporter()
        result = exporter.to_string(sample_profile)
        assert "completeness-bar" in result

    def test_contains_column_details(self, sample_profile):
        exporter = HtmlExporter()
        result = exporter.to_string(sample_profile)
        assert "eta" in result
        assert "nome" in result
