"""
Classe base astratta per gli analyzer di colonne.

Definisce l'interfaccia che ogni analyzer deve implementare:
- can_analyze(): determina se l'analyzer è adatto per una colonna
- analyze(): esegue l'analisi e restituisce un ColumnProfile
"""

from abc import ABC, abstractmethod

from dataprofiler.models.column_profile import ColumnProfile


class BaseAnalyzer(ABC):
    """Classe base astratta per tutti gli analyzer.

    Ogni analyzer è specializzato per un tipo di dato
    (numerico, testuale, data, ecc.) e implementa:

    - can_analyze(): determina se può analizzare la colonna
    - analyze(): esegue l'analisi statistica

    Il Profiler itera sugli analyzer registrati e usa il primo
    che risponde True a can_analyze() — questo è il polimorfismo
    in azione.
    """

    @abstractmethod
    def can_analyze(self, values: list, column_name: str) -> bool:
        """Determina se questo analyzer è adatto per la colonna.

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

        Returns:
            True se l'analyzer può gestire questi dati.
        """
        ...

    @abstractmethod
    def analyze(self, values: list, column_name: str) -> ColumnProfile:
        """Analizza i valori e restituisce un profilo colonna.

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

        Returns:
            ColumnProfile con le statistiche calcolate.
        """
        ...

    def _count_missing(self, values: list) -> int:
        """Conta i valori mancanti (None o stringa vuota).

        Args:
            values: Lista di valori.

        Returns:
            Numero di valori mancanti.
        """
        return sum(
            1 for v in values
            if v is None or (isinstance(v, str) and v.strip() == "")
        )

    def _get_non_null(self, values: list) -> list:
        """Filtra i valori non nulli e non vuoti.

        Args:
            values: Lista di valori.

        Returns:
            Lista dei soli valori non nulli.
        """
        return [
            v for v in values
            if v is not None and (not isinstance(v, str) or v.strip() != "")
        ]
