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

class Cores:
    """Classe para definir cores para saída no terminal."""
    VERDE_OK = '\033[92m'
    AVISO = '\033[93m'
    ERRO = '\033[91m'
    AZUL = '\033[94m'
    FIM = '\033[0m'

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{Cores.AZUL}{mensagem} {spinner[idx]}{Cores.FIM}", 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, service_name):
    """
    Executa um comando no terminal.

    Args:
        command (str): O comando a ser executado.
        docker_path (str): O caminho onde o comando deve ser executado.
        service_name (str): O nome do serviço Docker.

    Returns:
        bool: True se o comando foi executado com sucesso, False caso contrário.
    """
    try:
        print(f"{Cores.VERDE_OK}A executar: {command} no serviço {service_name}{Cores.FIM}")
        evento_concluido = threading.Event()
        spinner_thread = threading.Thread(target=mostrar_spinner, args=("A processar...", evento_concluido))
        spinner_thread.start()
        
        result = subprocess.run(f"docker compose exec {service_name} {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"{Cores.AVISO}{result.stderr}{Cores.FIM}")
        return result.returncode == 0
    except Exception as e:
        evento_concluido.set()
        spinner_thread.join()
        print(f"{Cores.ERRO}Erro ao executar o comando: {e}{Cores.FIM}")
        return False

def generate_swagger(docker_path):
    """
    Gera a documentação Swagger para os três serviços.

    Args:
        docker_path (str): O caminho onde os comandos Docker devem ser executados.
    """
    services = ["backoffice-marketplace", "bi"]
    command = "php artisan l5-swagger:generate"
    for service in services:
        if run_command(command, docker_path, service):
            print(f"{Cores.VERDE_OK}Documentação Swagger gerada com sucesso para {service}.{Cores.FIM}")
        else:
            print(f"{Cores.ERRO}Erro ao gerar documentação Swagger para {service}.{Cores.FIM}")

def main():
    """
    Função principal que coordena a geração da documentação Swagger.
    """
    def interromper_processo(signal_received, frame):
        evento_concluido.set()
        print(f"\n{Cores.AVISO}Processo interrompido pelo utilizador.{Cores.FIM}")
        sys.exit(0)

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

    print(f"{Cores.VERDE_OK}Início do processo de geração da documentação Swagger...{Cores.FIM}")
    docker_path = Path(__file__).resolve().parent.parent / 'docker'
    
    generate_swagger(docker_path)

    print(f"{Cores.VERDE_OK}Processo de geração da documentação Swagger concluído!{Cores.FIM}")

if __name__ == "__main__":
    main()
