###############################################################################
#
# (C) Copyright 2026 EVERYSK TECHNOLOGIES
#
# This is an unpublished work containing confidential and proprietary
# information of EVERYSK TECHNOLOGIES. Disclosure, use, or reproduction
# without authorization of EVERYSK TECHNOLOGIES is prohibited.
#
################################################################################
import pandas as pd

from everysk.sdk.brutils.cnpj import CNPJ


@pd.api.extensions.register_series_accessor('cnpj')
class CNPJAccessor:
    """
    A pandas accessor class for handling CNPJ (Cadastro Nacional da Pessoa Jurídica) operations on pandas Series.

    Parameters
    ----------
    pandas_obj : pandas.Series
        The pandas Series object containing CNPJ values.
    """

    def __init__(self, pandas_obj: pd.Series) -> None:
        """
        Initializes the class with a pandas Series object.

        Args:
            pandas_obj (pd.Series): The pandas Series to be associated with the instance.
        """
        self._obj = pandas_obj

    def sanitize(self, *, zfill: bool = True) -> pd.Series:
        """
        Sanitizes each CNPJ value in the Series.

        This method applies the `CNPJ.sanitize` function to each element of the Series,
        removing any non-numeric characters and optionally zero-padding the result to 14 digits.

        Args:
            zfill (bool, optional): If True, pads the sanitized CNPJ with leading zeros to ensure a length of 14 digits.
                Defaults to True.

        Returns:
            pd.Series: A Series containing the sanitized CNPJ values.
        """
        return self._obj.apply(lambda x: CNPJ(x).sanitize(zfill=zfill))

    def normalize(self, *, zfill: bool = False, errors: str = 'raise') -> pd.Series:
        """
        Normalize CNPJ numbers in the Series.

        This method applies normalization to each CNPJ value in the Series, optionally zero-filling
        the result to 14 digits. Invalid CNPJ values can be handled according to the `errors` parameter.

        Parameters
        ----------
        zfill : bool, default False
            If True, pad the CNPJ with leading zeros to ensure a length of 14 digits.
        errors : {'raise', 'ignore', 'coerce'}, default 'raise'
            Specifies how to handle invalid CNPJ values:
                - 'raise': Raise an exception for invalid values.
                - 'ignore': Return the original value for invalid entries.
                - 'coerce': Replace invalid values with NaN.

        Returns
        -------
        pd.Series
            A pandas Series with normalized CNPJ numbers.
        """
        return self._obj.apply(lambda x: CNPJ(x).normalize(zfill=zfill, errors=errors))

    def is_valid(self, *, check_dv: bool = False) -> pd.Series:
        """
        Check if each CNPJ in the Series is valid.

        Parameters
        ----------
        check_dv : bool, optional
            If True, also checks the verification digits (DV) of the CNPJ. Default is False.

        Returns
        -------
        pd.Series
            A boolean Series indicating whether each CNPJ is valid.
        """
        return self._obj.apply(lambda x: CNPJ(x).is_valid(check_dv=check_dv))

    def format(self, *, errors: str = 'raise') -> pd.Series:
        """
        Formats each value in the Series as a CNPJ string.

        Parameters
        ----------
        errors : str, default 'raise'
            Specifies how to handle parsing errors. If 'raise', an exception is raised for invalid CNPJ values.

        Returns
        -------
        pd.Series
            A Series with each value formatted as a CNPJ string.

        Examples
        --------
        >>> s = pd.Series(['12345678000195', '11222333000181'])
        >>> s.cnpj.format()
        0    12.345.678/0001-95
        1    11.222.333/0001-81
        dtype: object
        """
        return self._obj.apply(lambda x: CNPJ(x).format(errors=errors))

    def generate(self, *, valid_dv: bool = True) -> pd.Series:
        """
        Generate a pandas Series of random CNPJ numbers.

        Each element in the Series is a randomly generated CNPJ string.
        The validity of the check digits (DV) can be controlled via the `valid_dv` parameter.

        Args:
            valid_dv (bool, optional): If True, generates CNPJs with valid check digits.
                If False, generates CNPJs with invalid check digits. Defaults to True.

        Returns:
            pd.Series: A pandas Series containing randomly generated CNPJ strings.
        """
        return self._obj.apply(lambda _: str(CNPJ.generate_random(valid_dv=valid_dv)))
