import uuid
from typing import Dict, Any
import os
import shutil
from enum import Enum
# from pyspark.sql import SparkSession
import json
from app.main.engine.util.Timezone import Timezone

# from config import Config as cfg
from app.main.engine.enum.StatusEnum import StatusEnum
from app.main.engine.enum.SufixEnum import SufixEnum
from app.main.engine.enum.FixedFieldsEnum import FixedFieldsEnum
from app.main.engine.enum.DescResponseEnum import DescResponseEnum
from app.main.engine.models.ResultMode import ResultModel

class Utils:

    def __init__(self, app) -> None:
        self.app = app
        self.timezone = Timezone(app)

    def create_temp_file(self) -> str:
        fullpath = None
        try:
            dir_name = str(uuid.uuid4())
            path_dir = "/tmp/" + dir_name
            os.mkdir(path_dir)
            filename = str(uuid.uuid4()) + ".csv"
            fullpath = path_dir + "/" + filename
            open(fullpath, mode='a').close()
        except Exception as e:
            self.app.logger.error(f"Error creando directorio temporal.{e}")
        finally:
            return fullpath

    def delete_temp_dir(self, module_name: str) -> bool:
        drop = False
        try:
            if os.path.exists(module_name):
                directory = os.path.dirname(module_name)
                shutil.rmtree(directory, ignore_errors=True)
                self.app.logger.debug(f"directorio borrado: {module_name}")
        except Exception as e:
            raise AssertionError(f"Error borrando modulo temporal. {e}")
        finally:
            return drop

    def create_response(self, codeEnum: Enum, detail: str = "") -> Dict[str, Any]:
        response = {"statusCode": codeEnum.value}

        if codeEnum.value == StatusEnum.OK.value:
            response.update({'status': StatusEnum.OK.name, 'detail': detail})
        else:
            description = DescResponseEnum[codeEnum.name].value
            response.update({'status': StatusEnum.ERROR.name, 'message': description,
                             'detail': detail})
        return response

    def create_result(self, data, descriptor):
        result = []
        response = {"detail": result}
        try:
            exclude_pivot = descriptor["config-params"]["exclude-entity-pivot"]
            pivot_params = descriptor["params-input"]["pivot-config"]
            ctp_params = descriptor["params-input"]["counterpart-config"]

            group_pivot_match = pivot_params["columns-group"]
            transaction_pivot_match = pivot_params["columns-transaction"]

            group_counterpart_match = ctp_params["columns-group"]
            transaction_counterpart_match = ctp_params["columns-transaction"]

            used_list = transaction_counterpart_match if exclude_pivot else transaction_pivot_match

            if data.empty:
                self.app.logger.info(f"El dataframe resultado esta vacio")
            else:
                for idx, i in data.iterrows():
                    input_data = {}
                    key_transaction = None
                    key_group_pivot = None
                    key_group_counterpart = None
                    for element in used_list:
                        if key_transaction is None:
                            key_transaction = str(i[element])
                        else:
                            key_transaction = key_transaction + "-" + str(i[element])
                    for element_g in group_pivot_match:
                        if key_group_pivot is None:
                            key_group_pivot = str(i[element_g])
                        else:
                            key_group_pivot = key_group_pivot + "-" + str(i[element_g])
                    for element_c in group_counterpart_match:
                        if key_group_counterpart is None:
                            key_group_counterpart = str(i[element_c])
                        else:
                            key_group_counterpart = key_group_counterpart + "-" + str(i[element_c])
                    input_data["key-transaction"] = str(key_transaction)
                    input_data["key-group-pivot"] = "" if key_group_pivot is None else str(key_group_pivot)
                    input_data["key-group-counterpart"] = "" if key_group_counterpart is None else str(key_group_counterpart)
                    input_data["list-ids-pivot"] = str(i[FixedFieldsEnum.INTER_PIVOT_ID.value])
                    input_data["list-ids-counterpart"] = str(i[FixedFieldsEnum.INTER_CTP_ID.value])
                    input_data["exclude-ids"] = str(i[FixedFieldsEnum.LISTA_DIFF.value])
                    input_data["difference-amount"] = str(i[FixedFieldsEnum.DIFF.value])
                    result.append(input_data)
            response['status'] = StatusEnum.OK.value
            response["detail"] = result
        except Exception as e:
            self.app.logger.error(f"Error al crear el diccionario de resultados. {e}")
            response["status"] = StatusEnum.ERROR
            response["message"] = str(e)
        finally:
            return response

    def save_result(self, result, descriptor, Session):
        response = {}
        session = Session()
        try:
            d1 = self.timezone.datetime_by_tzone()

            result_json = json.dumps(result["detail"])
            result_obj = ResultModel(
                ID=None,
                ACTION_ID=descriptor["idScript"],
                ID_PROCESS=descriptor["idProcess"],
                CREATE_DATE=d1,
                KEY=FixedFieldsEnum.MATCH_RECORDS.value,
                RESULT_JSON=result_json
            )
            session.add(result_obj)
            session.commit()
            response['status'] = StatusEnum.OK.name
        except Exception as e:
            session.rollback()
            response["status"] = StatusEnum.ERROR.name
            response["message"] = str(e)
            self.app.logger.error(f"Error al guardar registro en la base de datos {e}")
        finally:
            session.close()
            return response
