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.
    """
    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):
    """
    Executa um comando no terminal.
    """
    try:
        print(f"{Cores.VERDE_OK}A executar: {command}{Cores.FIM}")
        evento_concluido = threading.Event()
        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"{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 reset_backoffice_marketplace(docker_path):
    """
    Reseta as migrations para o serviço backoffice_marketplace.
    """
    print(f"\n{Cores.AZUL}Drop de todas as tabelas e migrate backoffice-marketplace{Cores.FIM}")
    command = "docker compose exec backoffice-marketplace php artisan db:wipe && docker compose exec backoffice-marketplace php artisan migrate:reset"
    return run_command(command, docker_path)

def reset_bi(docker_path):
    """
    Reseta as migrations para o serviço bi.
    """
    print(f"\n{Cores.AZUL}Drop de todas as tabelas e migrate bi{Cores.FIM}")
    command = "docker compose exec bi php artisan db:wipe && docker compose exec bi php artisan migrate:reset"
    return run_command(command, docker_path)

def reset_shared(docker_path):
    """
    Reseta as migrations compartilhadas.
    """
    print(f"\n{Cores.AZUL}Drop de todas as tabelas e migrate backoffice-marketplace [SHARED]{Cores.FIM}")
    command = "docker compose exec backoffice-marketplace php artisan db:wipe && docker compose exec backoffice-marketplace php artisan migrate:reset --path=./shared/database/migrations"
    return run_command(command, docker_path)

def main():

    """
    Função principal que coordena a execução do reset das migrations.
    """
    evento_concluido = threading.Event()

    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 reset das migrações...{Cores.FIM}")
    docker_path = Path(__file__).resolve().parent.parent / 'docker'

    if reset_bi(docker_path):
        if reset_backoffice_marketplace(docker_path):
            if reset_shared(docker_path):
                print(f"{Cores.VERDE_OK}Todas as migrações foram resetadas com sucesso!{Cores.FIM}")
            else:
                print(f"{Cores.ERRO}Erro ao resetar shared.{Cores.FIM}")
        else:
            print(f"{Cores.ERRO}Erro ao resetar backoffice_marketplace.{Cores.FIM}")
    else:
        print(f"{Cores.ERRO}Erro ao resetar bi.{Cores.FIM}")

if __name__ == "__main__":
    main()
