from typing import Dict, Any
import time
import traceback as traceback_lib
import importlib

from config import Config as cfg
from app.main.engine.util.Timezone import Timezone
from app.main.engine.util.Utils import Utils
from app.main.engine.enum.StatusEnum import StatusEnum
from app.main.engine.enum.CodeResponseEnum import CodeResponseEnum
from app.main.engine.database.Database import Database


class Process:
    def __init__(self, app, descriptor: Dict[str, Any]) -> None:
        self.app = app
        self.descriptor = descriptor

        self.timezone = Timezone(app)
        self.utils = Utils(app)

    def run(self) -> Dict[str, Any]:
        status, status_description = StatusEnum.SUCCESS, ""
        try:
            # Obteniendo la conexión a la BD
            db_params = cfg.db_params
            source = Database(self.app, db_params)
            # Esta variable llega después de consultar en la BD el nombre del script de acuerdo al parámetro enviado
            script_name = "match-and-exclude-records-actions_v1.py"

            path_script = "scripts/"+script_name
            module = path_script[:-3].replace("/", ".")

            import_module = importlib.import_module(module)
            importlib.reload(import_module)
            globals().update(importlib.import_module(module).__dict__)

            # Parsea los parámetros de entrada
            relation = relation_classname_identifier[self.descriptor["idScript"]]
            obj_script = globals()[relation](self.app)

            obj_script.parser(self.descriptor)

            process = obj_script.process(source)

            response = obj_script.response()

        except IndexError as e:
            self.app.logger.error(f"Error extrayendo insumos. Vacío. Error: {e}")
            status, status_description = CodeResponseEnum.EMPTY_DATASET, str(e)
        except InterruptedError as e:
            self.app.logger.error(f"Error guardando resultados en bucket. Error: {e}")
            status, status_description = CodeResponseEnum.OUTPUT_ERROR, str(e)
        except BufferError as e:
            self.app.logger.error(f"Error obteniendo la data. Error: {e}")
            status, status_description = CodeResponseEnum.BD_INPUT_ERROR, str(e)
        except RuntimeError as e:
            self.app.logger.error(f"Error en la ejecución del script {self.descriptor['action_module_script']}. Error: {e}")
            status, status_description = CodeResponseEnum.SCRIPT_EXECUTION_ERROR, str(e)
        except ModuleNotFoundError as e:
            self.app.logger.error(f"Error obteniendo script {self.descriptor['action_module_script']}. Error: {e}")
            status, status_description = CodeResponseEnum.SCRIPT_ERROR, str(e)
        except ReferenceError as e:
            self.app.logger.error(f"Error validando parámetros del descriptor. {e}")
            status, status_description = CodeResponseEnum.PARAMETERS_ERROR, str(e)
        except Exception as e:
            traceback_lib.print_exc()
            self.app.logger.error(f"Error procesando engine. {e}")
            status, status_description = StatusEnum.ERROR, str(e)
        finally:
            return self.utils.create_response(status, status_description)
