"""
Analyzer per colonne con dati testuali.

Calcola statistiche sulle stringhe: lunghezze, frequenze dei valori,
top valori più comuni, e indicatori di unicità.
"""

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


class TextAnalyzer(BaseAnalyzer):
    """Analizza colonne contenenti dati testuali.

    Funge anche da fallback: se nessun altro analyzer riconosce
    la colonna, viene utilizzato il TextAnalyzer.

    Statistiche calcolate:
        - lunghezza minima, massima e media delle stringhe
        - top 5 valori più frequenti
        - flag se tutti i valori sono unici
        - flag se contiene stringhe vuote

    Esempio::

        analyzer = TextAnalyzer()
        values = ["Milano", "Roma", "Milano", "Napoli", None]
        profile = analyzer.analyze(values, "città")
        print(profile.stats["top_5_valori"])  # {"Milano": 2, "Roma": 1, ...}
    """

    def can_analyze(self, values: list, column_name: str) -> bool:
        """Restituisce True se la colonna non è numerica, data o booleana.

        Il TextAnalyzer è l'ultima risorsa: accetta tutto ciò che
        gli altri analyzer non riconoscono.

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

        Returns:
            True se la colonna è prevalentemente testuale.
        """
        non_null = self._get_non_null(values)
        if not non_null:
            return True  # Colonna vuota = fallback testuale

        # Non è testuale se è prevalentemente numerica
        numeric_count = sum(1 for v in non_null if is_numeric(v))
        if (numeric_count / len(non_null)) >= 0.70:
            return False

        # Non è testuale se è prevalentemente data
        date_count = sum(1 for v in non_null if is_datetime(v))
        if (date_count / len(non_null)) >= 0.70:
            return False

        # Non è testuale se è prevalentemente booleana
        bool_count = sum(1 for v in non_null if is_boolean(v))
        if (bool_count / len(non_null)) >= 0.70:
            return False

        return True

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

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

        Returns:
            ColumnProfile con tipo TEXT e statistiche calcolate.
        """
        non_null = [str(v) for v in values
                     if v is not None and str(v).strip() != ""]
        missing = len(values) - len(non_null)

        stats: dict = {}
        if non_null:
            lengths = [len(s) for s in non_null]

            # Conteggio frequenze
            freq: dict[str, int] = {}
            for v in non_null:
                freq[v] = freq.get(v, 0) + 1

            # Top 5 per frequenza
            top_5 = sorted(freq.items(), key=lambda x: x[1], reverse=True)[:5]

            stats = {
                "lunghezza_min": min(lengths),
                "lunghezza_max": max(lengths),
                "lunghezza_media": round(sum(lengths) / len(lengths), 1),
                "top_5_valori": dict(top_5),
                "tutti_unici": len(freq) == len(non_null),
                "valori_distinti": len(freq),
            }

        return ColumnProfile(
            name=column_name,
            dtype=ColumnType.TEXT,
            total_count=len(values),
            missing_count=missing,
            unique_count=len(set(non_null)),
            stats=stats,
        )
