import os

from lxml import etree
from xml.sax.saxutils import escape
import hashlib, base64

from ..Playbooks.Playbook import PlaybookCredentialCollection, FileCleanupTask
from ...Machine.PaedMLMachineCollection import MACHINE_COLLECTION
from ...Logging.Logger import log, Severity
from ..SetupStep import SetupStep

class ConfigurePfSense(SetupStep):
    def __init__(self):
        super().__init__()

    def _read_server_file_to_b64(self, file_path: str) -> str:
        try:
            content = MACHINE_COLLECTION.server.read_file(file_path).strip()
            return base64.b64encode(content).decode()
        except Exception as e:
            log(f"Error reading file {file_path}: {str(e)}", Severity.ERROR)
            raise e

    def get_xml(self) -> str:
        log('Reading current config...', Severity.TRACE)
        return MACHINE_COLLECTION.firewall.read_file('/conf/config.xml').decode()

    def run(self, file_cleanup_stack : list[FileCleanupTask], credentials: PlaybookCredentialCollection) -> bool:
        radius_secret = escape(credentials.fwradius)
        admin_secret = escape(credentials.root)
        ldapsuche_secret = escape(credentials.ldapsuche)
        admin_secret_md5 = escape(hashlib.md5(admin_secret.encode()).hexdigest())
        admin_secret_nt = escape(admin_secret_md5[:16])

        # Read certificate files and convert to base64 using the helper method
        cert_ca_b64 = self._read_server_file_to_b64("/etc/univention/ssl/ucsCA/CAcert.pem")
        cert_crt_b64 = self._read_server_file_to_b64(f"/etc/univention/ssl/{MACHINE_COLLECTION.firewall.get_hostname()}/cert.pem")
        cert_prv_b64 = self._read_server_file_to_b64(f"/etc/univention/ssl/{MACHINE_COLLECTION.firewall.get_hostname()}/private.key")
        admin_authorizedkeys_b64 = self._read_server_file_to_b64("/root/.ssh/id_ed25519.pub")

        xsl_file_path = "/etc/paedml-lis/pfsense_config_transformation_template.xsl"

        try:
            values = {
                'radius_secret': radius_secret,
                'admin_secret': admin_secret,
                'admin_secret_md5': admin_secret_md5,
                'ldapsuche_secret': ldapsuche_secret,
                'admin_authorizedkeys_b64': admin_authorizedkeys_b64,
                'cert_crt_b64': cert_crt_b64,
                'cert_prv_b64': cert_prv_b64,
                'cert_ca_b64': cert_ca_b64
            }
            xslt = MACHINE_COLLECTION.server.read_file(xsl_file_path).decode('utf-8') % values
            xsl = etree.fromstring(xslt)
            xml_config = etree.fromstring(self.get_xml())

            transform = etree.XSLT(xsl)
            new_config = transform(xml_config)

            # Apply the XSL transformation
            result = etree.tostring(new_config, pretty_print=True)
            MACHINE_COLLECTION.firewall.write_file('/conf/config.xml', result)
            MACHINE_COLLECTION.firewall.write_file('/conf.default/config.xml', result)

            log("Firewall configuration updated.")


            return True

        except Exception as e:
            log(f"Error configuring firewall: {str(e)}", Severity.ERROR)
            return False