"""
Analyzer per colonne con dati temporali (date e orari).

Rileva automaticamente il formato della data e calcola statistiche
come range temporale, data più/meno recente e formati rilevati.
"""

from datetime import datetime

from .base import BaseAnalyzer
from dataprofiler.models.column_profile import ColumnProfile, ColumnType
from dataprofiler.utils import is_datetime, is_numeric, parse_date


class DateTimeAnalyzer(BaseAnalyzer):
    """Analizza colonne contenenti date e orari.

    Rileva una colonna come temporale se almeno il 70% dei valori
    non-null sono parsabili come data in formati comuni italiani
    e internazionali.

    Statistiche calcolate:
        - data minima e massima
        - range temporale in giorni
        - formato più comune rilevato
        - numero di date distinte

    Esempio::

        analyzer = DateTimeAnalyzer()
        values = ["2024-01-15", "2024-03-20", "2024-06-01"]
        if analyzer.can_analyze(values, "data_ordine"):
            profile = analyzer.analyze(values, "data_ordine")
            print(profile.stats["range_giorni"])
    """

    DATETIME_THRESHOLD = 0.70

    def can_analyze(self, values: list, column_name: str) -> bool:
        """Verifica se la colonna contiene prevalentemente date.

        Esclude prima le colonne numeriche pure (per evitare che
        anni come "2024" vengano interpretati come date).

        Args:
            values: Lista dei valori della colonna.
            column_name: Nome della colonna.

        Returns:
            True se almeno il 70% dei valori sono date riconoscibili.
        """
        non_null = self._get_non_null(values)
        if not non_null:
            return False

        # Se è prevalentemente numerica, non è una data
        numeric_count = sum(1 for v in non_null if is_numeric(v))
        if (numeric_count / len(non_null)) >= 0.70:
            return False

        date_count = sum(1 for v in non_null if is_datetime(v))
        return (date_count / len(non_null)) >= self.DATETIME_THRESHOLD

    def analyze(self, values: list, column_name: str) -> ColumnProfile:
        """Calcola statistiche temporali sulla colonna.

        Args:
            values: Lista dei valori della colonna.
            column_name: Nome della colonna.

        Returns:
            ColumnProfile con tipo DATETIME e statistiche calcolate.
        """
        parsed_dates: list[datetime] = []
        missing = 0

        for v in values:
            if v is None or (isinstance(v, str) and v.strip() == ""):
                missing += 1
            else:
                dt = parse_date(v)
                if dt is not None:
                    parsed_dates.append(dt)
                else:
                    missing += 1

        stats: dict = {}
        if parsed_dates:
            sorted_dates = sorted(parsed_dates)
            date_range = sorted_dates[-1] - sorted_dates[0]

            # Trova il formato più comune
            format_freq: dict[str, int] = {}
            for v in values:
                if v is not None:
                    fmt = self._detect_format(v)
                    if fmt:
                        format_freq[fmt] = format_freq.get(fmt, 0) + 1

            most_common_fmt = ""
            if format_freq:
                most_common_fmt = max(format_freq, key=format_freq.get)

            stats = {
                "data_min": sorted_dates[0].strftime("%Y-%m-%d"),
                "data_max": sorted_dates[-1].strftime("%Y-%m-%d"),
                "range_giorni": date_range.days,
                "formato_comune": most_common_fmt,
                "date_distinte": len(set(d.date() for d in parsed_dates)),
            }

        return ColumnProfile(
            name=column_name,
            dtype=ColumnType.DATETIME,
            total_count=len(values),
            missing_count=missing,
            unique_count=len(set(str(d.date()) for d in parsed_dates)) if parsed_dates else 0,
            stats=stats,
        )

    @staticmethod
    def _detect_format(value) -> str | None:
        """Rileva il formato della data provando i pattern comuni."""
        from dataprofiler.utils import DATE_FORMATS
        text = str(value).strip()
        for fmt in DATE_FORMATS:
            try:
                datetime.strptime(text, fmt)
                return fmt
            except ValueError:
                continue
        return None
