import subprocess
import tempfile
import base64
import os


class DiffieHellmanConsoleManager():
    """Class for managing diffie-hellman crypto operations"""
    host_private_key = None
    host_public_key = None
    remote_public_key = None
    shared_key = None
    dh_params = None

    def generate_dh_params(self) -> str:
        """Method for generating Diffie-Hellman (DH) parameters"""

        # Generating DH parameters
        dhparam_command = ['openssl', 'dhparam', '2048']

        # Capturing result of generator command to string
        completed_process = subprocess.run(dhparam_command, check=True, capture_output=True, text=True)
        dhparam_output = completed_process.stdout

        # Returning DH parameters
        return dhparam_output

    def generate_host_private_key(self, dh_params: str) -> str:
        """Method for generating console private key for further usage in DH algorithms

        Args:
            dh_params (str): DH paramters, that are generated earlier

        Returns:
            str: console private key
        """

        # Creating temporary file with DH params
        with tempfile.NamedTemporaryFile(mode='w', delete=False) as temp_file:
            temp_file.write(dh_params)
            temp_filename = temp_file.name

        # Generating console private key
        generate_private_console_key_command = ['openssl', 'genpkey', '-paramfile', temp_filename]

        # Capturing result of generator command to string
        generator_command_invoker = subprocess.run(generate_private_console_key_command,
                                                   check=True,
                                                   capture_output=True,
                                                   text=True)
        command_result_output = generator_command_invoker.stdout

        # Closing and deleting temporary file
        temp_file.close()

        # Returning console private key
        return command_result_output

    def generate_host_public_key(self, host_private_key: str) -> str:
        """Method for generating console public key

        Args:
            host_private_key (str): console private key, that is used to create public key

        Returns:
            str: Console public key
        """
        # Creating temporary file with console private key
        with tempfile.NamedTemporaryFile(mode='w', delete=False) as temp_file:
            temp_file.write(host_private_key)
            temp_filename = temp_file.name

        # Generating console public key
        generate_private_console_key_command = ['openssl', 'pkey', '-in', temp_filename, '-pubout']

        # Capturing result of generator command to string
        generator_command_invoker = subprocess.run(generate_private_console_key_command,
                                                   check=True,
                                                   capture_output=True,
                                                   text=True)
        command_result_output = generator_command_invoker.stdout

        # Closing and deleting temporary file
        temp_file.close()

        # Returning console private key
        return command_result_output

    def decode_remote_public_key(self, encoded_public_key: str) -> str:
        """Method for decoding publice key, received from remote

        Args:
            encoded_public_key (str): encoded remote public key

        Returns:
            str: decoded remote public key
        """
        # TODO: Add exception handler if key could not be decoded
        decoded_public_key = base64.b64decode(encoded_public_key).decode('utf-8')
        return decoded_public_key

    def generate_shared_key(self, host_private_key: str, remote_public_key: str) -> str:
        """Method for creation shared key, that will be used to encrypt data between host and remote

        Args:
            host_private_key (str): console private key
            remote_public_key (str): remote public key

        Returns:
            str: shared key for encryption
        """

        # Creating temporary file with console private key
        with tempfile.NamedTemporaryFile(mode='w', delete=False) as host_private_key_file:
            host_private_key_file.write(host_private_key)
            host_private_key_filename = host_private_key_file.name

        # Creating temportaty file with remote public key
        with tempfile.NamedTemporaryFile(mode='w', delete=False) as remote_public_key_file:
            remote_public_key_file.write(remote_public_key)
            remote_public_key_filename = remote_public_key_file.name

        command = [
            "openssl", "pkeyutl", "-derive", "-inkey", host_private_key_filename,
            '-peerkey', remote_public_key_filename, "-out", "secretSharedClass.bin"
        ]

        subprocess.run(
            command,
            check=True,
        )
        # command_result_output = generator_command_invoker.stdout

        file_name = "secretSharedClass.bin"  # Specify the name of the file you want to delete

        with open(file_name, "rb") as shared_file:
            shared_secret = shared_file.read().hex()
            self.shared_key = shared_secret
        

        if os.path.exists(file_name):
            os.remove(file_name)
            print(f"File '{file_name}' deleted successfully.")
        else:
            print(f"File '{file_name}' does not exist.")
            
        # Closing and deleting temporary files
        host_private_key_file.close()
        remote_public_key_file.close()
        print("|"*60)
        print(self.shared_key)
        print("|"*60)

        return self.shared_key
