package ec.edu.espe.security.monitoring.modules.integrations.docker.utils;

import ec.edu.espe.security.monitoring.modules.features.credential.models.DatabaseCredential;
import ec.edu.espe.security.monitoring.modules.core.initializer.models.SystemParameters;
import ec.edu.espe.security.monitoring.modules.features.credential.repositories.DatabaseCredentialRepository;
import ec.edu.espe.security.monitoring.modules.core.initializer.repositories.SystemParametersRepository;
import ec.edu.espe.security.monitoring.common.encrypt.utils.AesEncryptorUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Paths;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.Optional;

@Slf4j
@RequiredArgsConstructor
@Component
public class MyCnfFileGenerator {

    private final DatabaseCredentialRepository databaseCredentialRepository;
    private final SystemParametersRepository systemParametersRepository;
    private final AesEncryptorUtil aesEncryptorUtil;

    /**
     * Generates the .my.cnf file based on the active MariaDB credentials.
     */
    public void generateMyCnfFile() {
        String absolutePath = getAbsolutePath();

        if (!ensureDirectoryExists(absolutePath)) return;

        Optional<DatabaseCredential> credentialOpt = getActiveDatabaseCredential();
        if (credentialOpt.isEmpty()) {
            log.warn("No se encontraron credenciales activas para MariaDB.");
            return;
        }

        DatabaseCredential credential = credentialOpt.get();
        String decryptedPassword;

        try {
            decryptedPassword = aesEncryptorUtil.decrypt(credential.getPassword());
        } catch (Exception e) {
            log.error("Error al desencriptar la contraseña: {}", e.getMessage());
            return;
        }

        if (decryptedPassword == null || decryptedPassword.isBlank()) {
            log.error("La contraseña desencriptada de MariaDB está vacía.");
            return;
        }

        writeMyCnfFile(absolutePath, credential.getUsername(), decryptedPassword, credential.getHost(), String.valueOf(credential.getPort()));
    }

    private String getAbsolutePath() {
        String currentDir = System.getProperty("user.dir");
        File parentDir = new File(currentDir).getParentFile();
        String absolutePath = Paths.get(parentDir.getAbsolutePath(), ".container", ".my.cnf").toString();
        log.debug("Ruta absoluta calculada: {}", absolutePath);
        return absolutePath;
    }

    private boolean ensureDirectoryExists(String absolutePath) {
        File parentDir = new File(absolutePath).getParentFile();
        if (!parentDir.exists() && !parentDir.mkdirs()) {
            log.error("No se pudo crear el directorio: {}", parentDir.getAbsolutePath());
            return false;
        }
        if (!parentDir.canWrite()) {
            log.error("El directorio no tiene permisos de escritura: {}", parentDir.getAbsolutePath());
            return false;
        }
        return true;
    }

    private Optional<DatabaseCredential> getActiveDatabaseCredential() {
        Optional<SystemParameters> existingParam = systemParametersRepository.findByNameAndIsActiveTrue("MARIADB");
        if (existingParam.isEmpty()) {
            log.error("No se encontró el parámetro de sistema '{}'.", "MARIADB");
            return Optional.empty();
        }
        return databaseCredentialRepository.findBySystemParameterAndIsActive(existingParam.get(), true);
    }

    public void writeMyCnfFile(String absolutePath, String user, String password, String host, String port) {
        if (host.equals("127.0.0.1") || host.equals("localhost")) {
            host = "host.docker.internal";
        }
        try (FileWriter writer = new FileWriter(absolutePath)) {
            String content = String.format(
                    "[client]%nuser=%s%npassword=%s%nhost=%s%nport=%s%n",
                    user, password, host, port
            );
            writer.write(content);
            log.info("Archivo .my.cnf creado exitosamente en la ruta: {}", absolutePath);
        } catch (IOException e) {
            log.error("Error al escribir el archivo .my.cnf: {}", e.getMessage());
        }
    }


    public static void main(String[] args) {
        // Genera 32 bytes de clave (256 bits)
        SecureRandom secureRandom = new SecureRandom();
        byte[] key = new byte[32]; // 256 bits
        secureRandom.nextBytes(key);

        // Codifica la clave en Base64
        String base64Key = Base64.getEncoder().encodeToString(key);

        // Imprime la clave generada
        System.out.println("Clave generada (Base64): " + base64Key);
    }
}



