import os
import subprocess
from logging_handler import LoggerHandler
from error_handler import ExportErrorMessages


class EmEncryptionManager:
    """
    class for handling EM encryption algorithm

    """

    @staticmethod
    def read_key_file(file_path):
        """
        :param file_path: path for file to read
        :return: return the content of the file in case of success, and None otherwise
        """
        LoggerHandler.print_message(f"start reading {file_path} file", logger_level='debug')
        if not os.path.exists(file_path):
            raise Exception(f"{ExportErrorMessages.KEY_FILE_IS_MISSING.value.format(file_path)}")
        try:
            with open(file_path, 'r') as file:
                file_content = file.read()
            LoggerHandler.print_message(f"finished reading {file_path} file", logger_level='debug')
            return file_content
        except Exception as e:
            raise Exception(f"{ExportErrorMessages.FAILED_TO_READ_KEY_FILE.value.format(file_path)}" + str(e))

    @staticmethod
    def encrypt_em_db_enc_key_file(em_export_directory, operation_system, em_home, em_version):
        """
        This method encrypt em_db_enc_key.txt using util command line
        :return:
        """
        exp_file_name = 'temp_onprem.txt_exp'
        db_enc_key_file_name = 'db_enc_key.txt'
        util_db_enc_exp_arg_name = "___db_enc_key_exp"
        file_path = os.path.join(em_export_directory, exp_file_name)
        db_enc_key_path = os.path.join(str(em_home), 'ini', 'fips', db_enc_key_file_name)
        if operation_system == 'Windows':
            open_ssl = f"\"{em_home}\\bin\\openssl.exe\""
            export_data_tool = 'util'
            quo = '\"'
        else:
            open_ssl = 'em openssl'
            export_data_tool = 'ecs -no_wrap util'
            quo = "\'"

        db_enc_key_value = EmEncryptionManager.read_key_file(db_enc_key_path)

        if db_enc_key_value is not None:
            if em_version < "9.0.21.000":
                """f'"{open_ssl} enc -aes-256-cbc -salt -a -in 'f'"{file_path}" -out "{db_enc_key_path}" -k {
                    ctm_key_value} '"""
                openssl_enc_cmd = f'{open_ssl} enc -aes-256-cbc -salt -a -in \"{db_enc_key_path}\" ' \
                                  f'-out \"{file_path}\" -k {db_enc_key_value}'
                openssl_enc_cmd_print = f'{open_ssl} enc -aes-256-cbc -salt -a -in \"{db_enc_key_path}\" ' \
                                        f'-out \"{file_path}\" -k *****db-enc-key*****'
            else:
                openssl_enc_cmd = f"{export_data_tool} -{util_db_enc_exp_arg_name} {db_enc_key_value} " \
                                  f"{quo}{file_path}{quo}"
                openssl_enc_cmd_print = f"{export_data_tool} -{util_db_enc_exp_arg_name} *****db-enc-key***** {quo}" \
                                        f"{file_path}{quo}"

            LoggerHandler.print_message(f"Running cmd - '{openssl_enc_cmd_print}'")
            process = subprocess.Popen(openssl_enc_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True,
                                       universal_newlines=True)
            # Wait for the process to finish and get the return code
            return_code = process.wait()

            # Get the output and error
            output, error = process.communicate()
            if return_code != 0:
                err = f"{ExportErrorMessages.FAILED_TO_ENCRYPT_DB_ENC_KEY_FILE.value} with return code: " \
                      f"{return_code} error: {error}"
                raise Exception(err)

            LoggerHandler.print_message(exp_file_name + ' successfully created on ' + em_export_directory)

        else:
            raise Exception(f"{ExportErrorMessages.FAILED_TO_READ_KEY_FILE.value.format(db_enc_key_path)}")
