import subprocess
import os
import sys
import signal
import threading
import time
from pathlib import Path

class Colors:
    """Classe para definir cores para saída no terminal."""
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    ENDC = '\033[0m'

services = ["backoffice-marketplace", "bi"]
shared_services = ["backoffice-marketplace", "bi"]

def mostrar_spinner(mensagem, evento_concluido):
    """
    Mostra um spinner de carregamento na linha de comando.

    Args:
        mensagem (str): A mensagem a ser exibida junto com o spinner.
        evento_concluido (threading.Event): Evento que sinaliza a conclusão do comando.
    """
    spinner = ['|', '/', '-', '\\']
    idx = 0
    while not evento_concluido.is_set():
        print(f"\r{mensagem} {spinner[idx]}", end='', flush=True)
        idx = (idx + 1) % len(spinner)
        time.sleep(0.1)
    print("\r" + " " * (len(mensagem) + 2), end='\r')

def run_command(command, docker_path):
    """
    Executa um comando no terminal.

    Args:
        command (str): O comando a ser executado.
        docker_path (str): O caminho onde o comando deve ser executado.
    """
    try:
        print(f"{Colors.OKGREEN}A executar: {command}{Colors.ENDC}")
        evento_concluido.clear()
        spinner_thread = threading.Thread(target=mostrar_spinner, args=("A processar...", evento_concluido))
        spinner_thread.start()
        
        result = subprocess.run(command, shell=True, cwd=docker_path, capture_output=True, text=True)
        
        evento_concluido.set()
        spinner_thread.join()
        
        if result.stdout:
            print(result.stdout)
        if result.stderr:
            print(f"{Colors.WARNING}{result.stderr}{Colors.ENDC}")
    except Exception as e:
        evento_concluido.set()
        spinner_thread.join()
        print(f"{Colors.WARNING}Erro ao executar o comando: {e}{Colors.ENDC}")

def update_composer_autoload(service_name, docker_path):
    """
    Atualiza o autoload do Composer para um serviço específico.

    Args:
        service_name (str): O nome do serviço Docker.
        docker_path (str): O caminho onde o comando Docker deve ser executado.
    """
    print(f"\nA atualizar o autoload do Composer para {service_name}...")
    if service_name in shared_services:
        command = f"docker compose exec -T {service_name} composer dump-autoload --working-dir=/shared/common_dependencies"
    else:
        command = f"docker compose exec -T {service_name} composer dump-autoload"
    run_command(command, docker_path)
    print(f"Autoload para {service_name} atualizado com sucesso.")

def main():
    """
    Função principal que inicia o processo de atualização do autoload do Composer.
    """
    def interromper_processo(signal_received, frame):
        evento_concluido.set()
        print(f"\n{Colors.WARNING}Processo interrompido pelo utilizador.{Colors.ENDC}")
        sys.exit(0)

    signal.signal(signal.SIGINT, interromper_processo)
    signal.signal(signal.SIGTERM, interromper_processo)

    print(f"{Colors.OKGREEN}Iniciando a atualização do autoload do Composer...{Colors.ENDC}")
    docker_path = Path(__file__).resolve().parent.parent / 'docker'
    
    for service in services:
        update_composer_autoload(service, docker_path)

    print("\nAtualização do autoload do Composer concluída com sucesso!")

if __name__ == "__main__":
    evento_concluido = threading.Event()
    main()
