import logging
import pandas as pd
import traceback

# =============== Writer ===============
class Writer:
    def __init__(self, logger: logging.Logger):
        # Logger
        self.logger: logging.Logger = logger
        # Raport 
        self.raportDataFrame: pd.DataFrame = self.create_raport()
        
    # ========== Create Raport Dataframe ==========
    def create_raport(self):
        """Creates the validation raport."""
        try:
            # Raport Columns
            columns = ["Nr. Regula", "Status", "Tip Alerta", 
                "Regula", "Definitie Tehnica", "Mesaj", "Modificare", "Verifica"]
            df = pd.DataFrame(columns = columns)
            
            return df
        except:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self.create_raport.__name__}] "
                f"Failed to create the raport dataframe. \n{traceBack}")
    # =============================================
    
    # ========== Write Pass ==========
    def validation_pass(self, rule: dict[str, str]) -> None:
        """Write the validation pass message inside the raport.

        Args:
            rule (dict[str, str]): The rule dictionary.
        """
        try:
            # The rows added if the rule is validated with success
            rule_row = [
                rule['numar_regula'],
                "Pass",
                self.alert_type(str(rule['tip_alerta_id'])),
                rule['descriere'],
                rule['definitie_tehnica'],
                rule['pass_alerta'],
                '-',
                '-'
            ]
            # Adds the rows based on the length of the raport dataframe
            self.raportDataFrame.loc[len(self.raportDataFrame)] = rule_row
        except:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self.validation_pass.__name__}] "
                f"Failed to write the validation pass message inside the raport. \n{traceBack}")
    # ================================
    
    # ========== Write Fail ==========
    def validation_fail(self, rule: dict[str, str], verify: str = "-") -> None:
        """Write the validation fail message inside the raport.

        Args:
            rule (dict[str, str]): _description_
            verify (str, optional): _description_. Defaults to "-".
        """
        try:
            # The rows added if the rule fails the validation
            rule_row = [
                rule['numar_regula'],
                "Fail",
                self.alert_type(str(rule['tip_alerta_id'])),
                rule['descriere'],
                rule['definitie_tehnica'],
                rule["fail_alerta"],
                rule['mesaj_modificare'],
                verify
            ]
            # Adds the rows based on the length of the raport dataframe
            self.raportDataFrame.loc[len(self.raportDataFrame)] = rule_row
        except:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self.validation_fail.__name__}] "
                f"Failed to write the validation fail message inside the raport. \n{traceBack}")
    # ================================
    
    # ========== Write Error ==========
    def validation_error(self, rule: dict[str, str], verify: str = "-") -> None:
        """Write the validation error message inside the raport.

        Args:
            rule (dict[str, str]): The rule dictionary.
            verify (str, optional): The error verification. Defaults to "-".
        """
        try:
            # The rows added if the rule errors during the validation
            rule_row = [
                rule['numar_regula'],
                "Error",
                self.alert_type(rule["tip_alerta_id"]),
                rule["descriere"],
                rule['definitie_tehnica'],
                rule["error_alerta"],
                rule['eroare_modificare'],
                verify
            ]
            # Adds the rows based on the length of the raport dataframe
            self.raportDataFrame.loc[len(self.raportDataFrame)] = rule_row
        except:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self.validation_error.__name__}] "
                f"Failed to write the validation error message inside the raport. \n{traceBack}")
    # =================================
    
    # ========== Extras ==========
    def alert_type(self, alert_type: str) -> str:
        """Converts the alert type into readable text

        Args:
            alert_type (str): The number as a string.

        Returns:
            str: The readable alert.
        """
        try:
            # Converts the alert type to a readable string
            alert_type = str(alert_type).strip()
            if alert_type.isdigit():
                alert_mapping = {1: "Blocker", 2: "Warning"}
                return alert_mapping.get(int(alert_type), alert_type)
            return alert_type
        except:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self.alert_type.__name__}] "
                f"Failed to change the alert type id into readable text. \n{traceBack}")
            
    def mark_validation_raport(self, template_version: str, plan_type: str, validation_package_version: str) -> None:
        """Marks the raport with the template version and plan type.

        Args:
            template_version (str): Template version.
            plan_type (str): The plan type.
            validation_package_version (str): The version of the validation package.
        """
        try:
            # The rows added for marking
            rule_row = [
                f"Versiune Pachet Validate: {validation_package_version}",
                f"Versiune Template: {template_version}",
                f"Tip Plan Urbanistic: {plan_type}",
                "-",
                "-",
                "-",
                "-",
                "-"
            ]
            # Adds the rows based on the length of the raport dataframe
            self.raportDataFrame.loc[len(self.raportDataFrame)] = rule_row
        except:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self.mark_validation_raport.__name__}] "
                f"Failed to mark the validation raport. \n{traceBack}")
    # ============================
# ======================================