import os
import json
import subprocess
import shutil
import logging

# Configuración básica del logger
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Cargar configuración desde config.json
PROGRAM_DIR = os.path.dirname(os.path.abspath(__file__))
config_file = os.path.join(PROGRAM_DIR, 'config.json')
with open(config_file, 'r') as f:
    config = json.load(f)

# Extraer parámetros relevantes
INSTALL_OGBOOT_TARGET = config["ogBoot_Dir"]


def og_boot_copy_files():
    """
    Copia los archivos necesarios al punto de montaje de ogBoot.
    Preserva el directorio client/images si existe.
    """
    repo_dir = os.path.dirname(PROGRAM_DIR)  # Ruta al directorio ogboot
    directories = {
        "bin": os.path.join(repo_dir, "bin"),
        "src": os.path.join(repo_dir, "src"),
        "config": os.path.join(repo_dir, "config"),
        "lib": os.path.join(repo_dir, "lib"),
        "client": os.path.join(repo_dir, "client"),
    }

    for key, source in directories.items():
        dest = os.path.join(INSTALL_OGBOOT_TARGET, key)
        if key == "client":
            # Preservar el directorio client/images si existe
            images_dir = os.path.join(dest, "images")
            if os.path.exists(images_dir):
                temp_images_dir = os.path.join("/tmp", "ogboot_client_images")
                logger.info(f"Preservando el directorio {images_dir} temporalmente en {temp_images_dir}.")
                shutil.move(images_dir, temp_images_dir)
            # Reemplazar todo el directorio client
            if os.path.exists(dest):
                shutil.rmtree(dest)
            shutil.copytree(source, dest)
            # Restaurar el directorio images
            if os.path.exists(temp_images_dir):
                os.makedirs(dest, exist_ok=True)
                shutil.move(temp_images_dir, os.path.join(dest, "images"))
                logger.info(f"Directorio images restaurado en {dest}.")
        else:
            # Reemplazar otros directorios
            if os.path.exists(dest):
                shutil.rmtree(dest)
            shutil.copytree(source, dest)
            logger.info(f"Copiado {key} desde {source} a {dest}.")

    # Crear directorios adicionales si no existen
    additional_dirs = ["etc", "public"]
    for dir_name in additional_dirs:
        os.makedirs(os.path.join(INSTALL_OGBOOT_TARGET, dir_name), mode=0o775, exist_ok=True)

    subprocess.run(["chmod", "-R", "775", INSTALL_OGBOOT_TARGET])
    subprocess.run(["chown", "-R", "opengnsys:opengnsys", INSTALL_OGBOOT_TARGET])
    logger.info("Archivos copiados y permisos ajustados correctamente.")


def og_boot_composer_install():
    """
    Ejecuta Composer para instalar y actualizar las dependencias.
    """
    result = subprocess.run(
        ["sudo", "-u", "opengnsys", "composer", "install", "--no-interaction", "--working-dir", INSTALL_OGBOOT_TARGET]
    )
    if result.returncode != 0:
        logger.error("Error creando el proyecto Symfony usando Composer.")
        return False
    result = subprocess.run(
        ["sudo", "-u", "opengnsys", f"{INSTALL_OGBOOT_TARGET}/bin/composer.phar", "update", "doctrine/dbal",
         "--working-dir", INSTALL_OGBOOT_TARGET]
    )
    if result.returncode != 0:
        logger.error("Error actualizando el paquete doctrine/dbal usando Composer.")
        return False

    subprocess.call(["chown", "-R", "opengnsys:opengnsys", f"{INSTALL_OGBOOT_TARGET}/public"])
    logger.info("Composer ejecutado correctamente y permisos ajustados.")
    return True


if __name__ == "__main__":
    try:
        og_boot_copy_files()

        if not og_boot_composer_install():
            raise Exception("Error en la ejecución de Composer.")

        logger.info("Actualización de ogBoot completada correctamente.")
    except Exception as e:
        logger.error(f"ERROR\tFallo crítico: {e}")
