"""
Reader per file Excel (.xlsx, .xls).

Utilizza la libreria openpyxl per leggere file Excel moderni.
"""

from typing import Any

from .base import BaseReader
from dataprofiler.exceptions import DataReadError


class ExcelReader(BaseReader):
    """Reader per file in formato Excel (.xlsx, .xls).

    Legge il primo foglio del file Excel (o un foglio specifico)
    e lo converte in una lista di dizionari.

    Args:
        filepath: Percorso del file Excel.
        sheet_name: Nome del foglio da leggere (default: il primo).

    Esempio::

        reader = ExcelReader("vendite.xlsx")
        dati = reader.read()

        # Foglio specifico
        reader = ExcelReader("vendite.xlsx", sheet_name="Gennaio")
    """

    def __init__(self, filepath: str, sheet_name: str | None = None, **kwargs):
        super().__init__(filepath)
        self._sheet_name = sheet_name
        self._headers: list[str] = []

    def read(self) -> list[dict[str, Any]]:
        """Legge il file Excel e restituisce lista di dizionari.

        Returns:
            Lista di dizionari dove ogni chiave è un nome di colonna.

        Raises:
            DataReadError: Se il file non può essere letto.
        """
        try:
            from openpyxl import load_workbook

            wb = load_workbook(self._filepath, read_only=True, data_only=True)

            # Seleziona il foglio
            if self._sheet_name:
                if self._sheet_name not in wb.sheetnames:
                    raise DataReadError(
                        f"Foglio '{self._sheet_name}' non trovato. "
                        f"Fogli disponibili: {', '.join(wb.sheetnames)}"
                    )
                ws = wb[self._sheet_name]
            else:
                ws = wb.active

            rows: list[dict[str, Any]] = []
            row_iter = ws.iter_rows(values_only=True)

            # Prima riga = header
            header_row = next(row_iter, None)
            if header_row is None:
                wb.close()
                return rows

            self._headers = [
                str(h) if h is not None else f"colonna_{i}"
                for i, h in enumerate(header_row)
            ]

            # Righe dati
            for row in row_iter:
                row_dict: dict[str, Any] = {}
                for i, value in enumerate(row):
                    if i < len(self._headers):
                        # Converti valori vuoti in None
                        if value is not None and str(value).strip() == "":
                            value = None
                        row_dict[self._headers[i]] = value
                rows.append(row_dict)

            wb.close()
            return rows

        except ImportError:
            raise DataReadError(
                "La libreria 'openpyxl' è necessaria per leggere file Excel. "
                "Installala con: pip install openpyxl"
            )
        except DataReadError:
            raise
        except Exception as e:
            raise DataReadError(
                f"Errore nella lettura del file Excel '{self._filepath}': {e}"
            )

    def get_headers(self) -> list[str]:
        """Restituisce i nomi delle colonne del foglio Excel.

        Returns:
            Lista dei nomi delle colonne.
        """
        if not self._headers:
            self.read()  # Deve leggere per ottenere gli header
        return self._headers
