from lib.ClienteLinux import TipoConexao, obter_cliente_linux
from lib.echo import echo
import sys
from pathlib import Path
from lib.obter_configuracoes import obter_configuracoes
from lib.obter_configuracoes import salvar_configuracoes
from lib.criptografia_senha import descriptografar
from lib.executar_validacoes_servidor_linux import executar_validacoes_servidor_linux
from lib.backup_volume import fazer_backup_volume_docker, restaurar_backup_volume_docker
from lib.shared_network import garantir_shared_network, conectar_container_shared_network
from lib.nomes_containers import (
    obter_nome_container_api_gateway,
    obter_nome_container_enterprise,
    obter_nome_container_enterprise_event_handler,
    obter_nome_container_enterprise_renderizador,
)
from lib.rede_externa import (
    deve_forcar_uso_rede_externa,
    obter_host_microkafka_para_enterprise,
    obter_host_porta_mu_whatsapp_para_enterprise,
)
from lib.substituir_placeholders import substituir_placeholders_arquivo
import os
import shutil


arquivo_configuracao = None if len(sys.argv) < 2 else sys.argv[1]
diretorio_scripts_implantacao = r'c:\microuniversoWeb' if len(sys.argv) < 3 else sys.argv[2]

configuracoes = obter_configuracoes(arquivo_configuracao)

if not configuracoes:
    echo(f"Falha ao carregar configuracoes do arquivo {arquivo_configuracao}" , "error")
    exit(1)

if not configuracoes["acessos"]["servidorLinux"]["configurar"]:
    echo("Dados do servidor linux nao informados. API Enterprise nao sera configurada")
    exit(0)

if not configuracoes["enterprise"]["configurar"]:
    echo(f"Configuracao da API Enterprise desativada via configuracao")
    exit(0)

mensagem_erro = executar_validacoes_servidor_linux(arquivo_configuracao, diretorio_scripts_implantacao)    

if mensagem_erro:
    echo(mensagem_erro, "error")
    exit(1)

cliente_linux = obter_cliente_linux(arquivo_configuracao)


usuario = configuracoes['acessos']['servidorLinux']['usuario']    


cliente_linux.executar_comando(f'mkdir -p /home/{usuario}/enterprise')
    
configurar_renderizador = configuracoes["enterprise"]["renderizador"]["configurar"]

compose_normal = "docker-compose-enterprise-linux.yml"
compose_renderizador = "docker-compose-renderizador.yml"


cliente_linux.copiar_arquivo(fr'{diretorio_scripts_implantacao}\enterprise\docker-compose-enterprise-linux.yml' , f'/home/{usuario}/enterprise/'+ compose_normal)
cliente_linux.copiar_arquivo(fr'{diretorio_scripts_implantacao}\enterprise\docker-compose-renderizador.yml' , f'/home/{usuario}/enterprise/'+ compose_renderizador)

imagem_enterprise = configuracoes["enterprise"]["imagem"]["nome"] + ":" + configuracoes["enterprise"]["imagem"]["versao"]
configurar_event_handler = configuracoes["enterprise"]["eventHandler"]["configurar"]
host_banco = configuracoes["acessos"]["banco"]["host"]
usuario_banco = configuracoes["acessos"]["banco"]["usuario"]
senha_banco = descriptografar(configuracoes["acessos"]["banco"]["senha"])
nome_banco = configuracoes["acessos"]["banco"]["nomeBanco"]
ip_host = configuracoes["enderecos"]["ipHost"]
porta_mu_dll_rest = configuracoes["muDllRest"]["porta"]
porta_enterprise = configuracoes["enterprise"]["porta"]
porta_enterprise_interna = str(
    configuracoes["enterprise"]["portaInterna"]
    if "portaInterna" in configuracoes["enterprise"]
    else 5000
)
neocredit_envio_processamento_url = configuracoes["enterprise"]["neocredit"]["urlProcessamento"]
neocredit_token = configuracoes["enterprise"]["neocredit"]["tokenNeocredit"]
neocredit_url_webhook = configuracoes["enterprise"]["neocredit"]["urlWebhook"]
porta_rest_legado = configuracoes["servicos"]["rest"]["porta"]
sql_server_2008 = "S" if configuracoes["enterprise"]["usarSQLServer2008"] else "N"
usuario_registro_docker = configuracoes["acessos"]["registroDocker"]["usuario"]
senha_registro_docker = configuracoes["acessos"]["registroDocker"]["senha"]
ativar_reprocessamento_custo_medio_online = "S" if configuracoes["enterprise"]["reprocessamentoCustoMedioOnline"]["ativar"] else "N"
hora_reprocessamento_custo_medio_online = configuracoes["enterprise"]["reprocessamentoCustoMedioOnline"]["hora"]
minuto_reprocessamento_custo_medio_online = configuracoes["enterprise"]["reprocessamentoCustoMedioOnline"]["minuto"]
ativar_job_retorno_coleta_preco_sigepro = "S" if configuracoes["coletaPrecos"]["agenda"]["ativar"] else "N"
valor_hora_cron_job_retorno_coleta_preco_sigepro = configuracoes["coletaPrecos"]["agenda"]["hora"]
token_acesso_logs = configuracoes["enterprise"]["tokenAcessoLogs"]
api_key_integracao_tecnospeed = configuracoes["enterprise"]["tecnospeed"]["apikey"]



mongodb_sites_iis_host = configuracoes["mongodbSitesIIS"]["endereco"]
mongodb_sites_iis_port = configuracoes["mongodbSitesIIS"]["porta"]
mongodb_sites_iis_user = configuracoes["mongodbSitesIIS"]["usuario"]
mongodb_sites_iis_password = configuracoes["mongodbSitesIIS"]["senha"]



ip_enterprise = configuracoes["servicos"]["rest"]["hostEnterprise"]

imagem_renderizador = configuracoes["enterprise"]["renderizador"]["imagem"]["nome"] + ":" + configuracoes["enterprise"]["imagem"]["versao"]
porta_renderizador = configuracoes["enterprise"]["renderizador"]["porta"]
memoria_minima_em_mb_heap_renderizador = configuracoes["enterprise"]["renderizador"]["memoriaMinimaEmMB"]
memoria_maxima_em_mb_heap_renderizador = configuracoes["enterprise"]["renderizador"]["memoriaMaximaEmMB"]

configurar_api_mu_whatsapp = configuracoes["muWhatsapp"]["configurarApi"]
nome_container_enterprise = obter_nome_container_enterprise(configuracoes)
nome_container_enterprise_event_handler = obter_nome_container_enterprise_event_handler(configuracoes)
nome_container_enterprise_renderizador = obter_nome_container_enterprise_renderizador(configuracoes)
nome_container_api_gateway = obter_nome_container_api_gateway(configuracoes)
certificados_pix_configurados = configuracoes["enterprise"]["certificadosPix"]["configurado"]
certificados_pix_ambiente_teste ="S" if configuracoes["enterprise"]["certificadosPix"]["ambienteTeste"] else "N"


licenciamento_timeout_sessao_segundos = configuracoes["enterprise"]["licenciamento"]["timeoutSessaoSegundos"]
ativar_job_encerrar_sessoes_zumbis = configuracoes["enterprise"]["licenciamento"]["ativarJobEncerrarSessoesZumbis"]
valor_hora_cron_job_encerrar_sessoes_zumbis = configuracoes["enterprise"]["licenciamento"]["horaJobEncerrarSessoesZumbis"]
valor_minuto_cron_job_encerrar_sessoes_zumbis = configuracoes["enterprise"]["licenciamento"]["minutoJobEncerrarSessoesZumbis"]

versao_enterprise = configuracoes["enterprise"]["imagem"]["versao"]

versaoReal = versao_enterprise.replace("-linux","")

ehVersaoOficial = len(versaoReal.split(".")) == 3 and all(parte.isdigit() for parte in versaoReal.split("."))
major = versaoReal.split(".")[0] if ehVersaoOficial else "0"
minor = versaoReal.split(".")[1] if ehVersaoOficial else "0"
patch = versaoReal.split(".")[2] if ehVersaoOficial else "0"

versao_com_geracao_de_token = "5.1.7"  # versão a partir da qual a api enterprise passou a ter geração de token 

    
autenticacao_usuario = (
    configuracoes["enterprise"]["autenticacaoUsuario"]
    if not ehVersaoOficial or (major, minor, patch) >= tuple(versao_com_geracao_de_token.split("."))
    else "REST_LEGADO"
)

tempo_cache_validacao_token_usuario_segundos = configuracoes["enterprise"]["tempoCacheValidacaoTokenUsuarioSegundos"]
ip_linux = configuracoes["acessos"]["servidorLinux"]["host"] if configuracoes["acessos"]["servidorLinux"]["host"] else ip_enterprise

garantir_shared_network(cliente_linux)

host_mu_whatsapp, porta_mu_whatsapp = obter_host_porta_mu_whatsapp_para_enterprise(configuracoes)
microkafka_host = obter_host_microkafka_para_enterprise(configuracoes)



cliente_linux.executar_comando(fr'docker login gitlab.microuniverso.com.br:5050 -u {usuario_registro_docker} -p {senha_registro_docker}', disparar_excecao_se_retorno_nao_zero=False)

for arquivo in [compose_normal]:
    caminho_compose = f"/home/{usuario}/enterprise/{arquivo}"

    substituir_placeholders_arquivo(
        cliente_linux,
        caminho_compose,
        {
            r"\$IMAGEM": imagem_enterprise,
            r"\$NOME_CONTAINER_ENTERPRISE": nome_container_enterprise,
            r"\$NOME_CONTAINER_ENTERPRISE_EVENT_HANDLER": nome_container_enterprise_event_handler,
            r"\$PORTA": porta_enterprise,
            r"\$PORTA_INTERNA": porta_enterprise_interna,
            r"\$MICROKAFKA_HOST": microkafka_host,
        }
    )

    
substituir_placeholders_arquivo(
    cliente_linux,
    f"/home/{usuario}/enterprise/{compose_renderizador}",
    {
        r"\$IMAGEM": imagem_enterprise,
        r"\$NOME_CONTAINER_ENTERPRISE": nome_container_enterprise,
        r"\$NOME_CONTAINER_ENTERPRISE_EVENT_HANDLER": nome_container_enterprise_event_handler,
        r"\$PORTA": porta_enterprise,
        r"\$PORTA_INTERNA": porta_enterprise_interna,
        r"\$MICROKAFKA_HOST": microkafka_host,
        r"\$RENDERIZADOR_IMAGEM": imagem_renderizador,
        r"\$NOME_CONTAINER_ENTERPRISE_RENDERIZADOR": nome_container_enterprise_renderizador,
        r"\$RENDERIZADOR_PORTA": porta_renderizador,
        r"\$MEMORIA_MINIMA_RENDERIZADOR": memoria_minima_em_mb_heap_renderizador,
        r"\$MEMORIA_MAXIMA_RENDERIZADOR": memoria_maxima_em_mb_heap_renderizador,
    }
)

cliente_linux.copiar_arquivo(fr'{diretorio_scripts_implantacao}\enterprise\config.env' , f'/home/{usuario}/enterprise/config.env')

cliente_linux.executar_comando(fr"sed -i 's,\$AUTENTICACAO_USUARIO,{autenticacao_usuario},g' /home/{usuario}/enterprise/config.env")
host_banco_ajustado=host_banco.replace("\\","#@#") 
cliente_linux.executar_comando(fr"sed -i 's,\$DB_HOST,{host_banco_ajustado},g' /home/{usuario}/enterprise/config.env")
if(cliente_linux.tipo_conexao == TipoConexao.SSH):  
    cliente_linux.executar_comando(fr"sed -i 's/#@#/\\/g' /home/{usuario}/enterprise/config.env")
if(cliente_linux.tipo_conexao == TipoConexao.WSL):
    cliente_linux.executar_comando(fr"sed -i 's/#@#/\\\\/g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$DB_NAME,{nome_banco},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$DB_PASSWORD,{senha_banco},g' /home/{usuario}/enterprise/config.env", echoar=False,descricao="Alterando senha do banco")
cliente_linux.executar_comando(fr"sed -i 's,\$DB_PORT,1433,g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$DB_USER,{usuario_banco},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$MU_DLL_REST_API_ADDRESS,{ip_host},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$MU_DLL_REST_API_PORT,{porta_mu_dll_rest},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$NEOCREDIT_ENVIO_PROCESSAMENTO_URL,{neocredit_envio_processamento_url},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$NEOCREDIT_TOKEN,{neocredit_token},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$REST_LEGADO_HOST,{ip_host},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$REST_LEGADO_PORTA,{porta_rest_legado},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$WEB_HOOK_URL,{neocredit_url_webhook},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$USANDO_SQLSERVER_2008,{sql_server_2008},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$ATIVAR_JOB_REPROCESSAMENTO_CUSTO_MEDIO_ONLINE,{ativar_reprocessamento_custo_medio_online},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$VALOR_HORA_CRON_JOB_REPROCESSAMENTO_CUSTO_MEDIO_ONLINE,{hora_reprocessamento_custo_medio_online},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$VALOR_MINUTO_CRON_JOB_REPROCESSAMENTO_CUSTO_MEDIO_ONLINE,{minuto_reprocessamento_custo_medio_online},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$ATIVAR_JOB_RETORNO_COLETA_PRECO_SIGEPRO,{ativar_job_retorno_coleta_preco_sigepro},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$VALOR_HORA_CRON_JOB_RETORNO_COLETA_PRECO_SIGEPRO,{valor_hora_cron_job_retorno_coleta_preco_sigepro},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$TOKEN_ACESSO_LOGS,{token_acesso_logs},g' /home/{usuario}/enterprise/config.env")



cliente_linux.executar_comando(fr"sed -i 's,\$MU_WHATSAPP_API_HOST,{host_mu_whatsapp},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$MU_WHATSAPP_API_PORT,{porta_mu_whatsapp},g' /home/{usuario}/enterprise/config.env")
    
cliente_linux.executar_comando(fr"sed -i 's,\$API_KEY_INTEGRACAO_TECNOSPEED,{api_key_integracao_tecnospeed},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$AMBIENTE_TESTE_INTEGRACAO_PIX_PRAZO,{certificados_pix_ambiente_teste},g' /home/{usuario}/enterprise/config.env")

cliente_linux.executar_comando(fr"sed -i 's,\$LICENCIAMENTO_TIMEOUT_SESSAO_SEGUNDOS,{licenciamento_timeout_sessao_segundos},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$ATIVAR_JOB_ENCERRAR_SESSOES_ZUMBIS,{ativar_job_encerrar_sessoes_zumbis},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$VALOR_HORA_CRON_JOB_ENCERRAR_SESSOES_ZUMBIS,{valor_hora_cron_job_encerrar_sessoes_zumbis},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$VALOR_MINUTO_CRON_JOB_ENCERRAR_SESSOES_ZUMBIS,{valor_minuto_cron_job_encerrar_sessoes_zumbis},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$VALIDAR_TOKEN_USUARIO_CACHE_TTL_SEGUNDOS,{tempo_cache_validacao_token_usuario_segundos},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$IP_SERVIDOR_LINUX,{ip_linux},g' /home/{usuario}/enterprise/config.env")

cliente_linux.executar_comando(fr"sed -i 's,\$SERVIDOR_MONGO,{mongodb_sites_iis_host},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$USUARIO_MONGO,{mongodb_sites_iis_user},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$SENHA_MONGO,{mongodb_sites_iis_password},g' /home/{usuario}/enterprise/config.env")
cliente_linux.executar_comando(fr"sed -i 's,\$PORTA_MONGO,{mongodb_sites_iis_port},g' /home/{usuario}/enterprise/config.env")

try:
    fazer_backup_volume_docker("enterprise_tokens-muwhatsapp-volume", arquivo_configuracao)
except Exception as e:
    echo(f"[WARN] Falha ao fazer backup do volume 'enterprise_tokens-muwhatsapp-volume': {str(e)}", "info")
    
try:
    cliente_linux.executar_comando(f'docker compose -f /home/{usuario}/enterprise/{compose_renderizador} down')
except Exception as e:
    echo(f"[WARN] Falha ao dar down no compose renderizador ({compose_renderizador}): {str(e)}", "info")
    
try:
    cliente_linux.executar_comando(f'docker compose -f /home/{usuario}/enterprise/{compose_normal} down')
except Exception as e:
    echo(f"[WARN] Falha ao dar down no compose normal ({compose_normal}): {str(e)}", "info")

arquivo_docker_compose = compose_renderizador if configurar_renderizador else compose_normal

try:
    cliente_linux.executar_comando(f'docker compose -f /home/{usuario}/enterprise/' + arquivo_docker_compose + ' pull')    
    cliente_linux.executar_comando(f'docker compose -f /home/{usuario}/enterprise/' + arquivo_docker_compose + ' up -d')    
except Exception as e:
    echo(f"Não foi possível configurar a Api Enterprise com o Renderizador.Configurando apenas a Api Enterprise no lugar. Detalhe do erro: {str(e)}", "info")
    cliente_linux.executar_comando(f'docker compose -f /home/{usuario}/enterprise/' + compose_normal + ' pull')    
    cliente_linux.executar_comando(f'docker compose -f /home/{usuario}/enterprise/' + compose_normal + ' up -d')    

if not deve_forcar_uso_rede_externa(configuracoes):
    conectar_container_shared_network(cliente_linux, nome_container_api_gateway, reiniciar_apos_conexao=True)

if not configurar_event_handler:
    cliente_linux.executar_comando(f'docker compose -f /home/{usuario}/enterprise/' + arquivo_docker_compose + ' rm -fs enterprise-event-handler')

try:
    if configurar_api_mu_whatsapp:
        restaurar_backup_volume_docker("enterprise_tokens-muwhatsapp-volume", arquivo_configuracao)
except Exception as e:
    echo(f"[WARN] Falha ao restaurar backup do volume 'enterprise_tokens-muwhatsapp-volume' após a configuração: {str(e)}", "info")

pastaTemporariaItauCerts = configuracoes["enterprise"]["certificadosPix"]["pastaTemporaria"]

if not pastaTemporariaItauCerts:
    echo("Pasta temporaria dos certificados Pix nao informada. Nao sera copiada para o servidor Linux.", "info")


arquivos_enc = [f for f in os.listdir(pastaTemporariaItauCerts) if f.endswith('.enc')] if pastaTemporariaItauCerts and os.path.exists(pastaTemporariaItauCerts) else []
if len(arquivos_enc) % 2 != 0 and len(arquivos_enc) <= 2:
    echo("Pasta temporaria dos certificados Pix invalida. Devem existir os dois arquivos ou nenhum deles.", "error")
    exit(1)

if  pastaTemporariaItauCerts and os.path.exists(pastaTemporariaItauCerts) and len(arquivos_enc) == 2:
    try:
        cliente_linux.executar_comando(f'rm -rf /home/{usuario}/certificadoPix')
    except Exception as e:
        echo(f"[WARN] Falha ao remover pasta /home/{usuario}/certificadoPix no servidor Linux: {str(e)}", "info")
    cliente_linux.executar_comando(f'mkdir -p /home/{usuario}/certificadoPix')

    for arquivo in arquivos_enc:
        cliente_linux.copiar_arquivo(
            fr'{pastaTemporariaItauCerts}\{arquivo}',
            f'/home/{usuario}/certificadoPix/{arquivo}'
        )
    
    cliente_linux.executar_comando(f'docker stop {nome_container_enterprise}')
    
    cliente_linux.executar_comando(
        f"docker run --rm "
        f"-v enterprise_certs_volume:/certs "
        f"-v /home/{usuario}/certificadoPix:/from "
        f"busybox sh -c 'cp /from/*.enc /certs/'"
    )
    cliente_linux.executar_comando(f'docker start {nome_container_enterprise}')
    
    # configuracoes["enterprise"]["certificadosPix"]["configurado"] = True
    # salvar_configuracoes(arquivo_configuracao, configuracoes)
    # nao funciona de forma confiavel
    certificados_pix_configurados = True
    
    
if( not certificados_pix_configurados):
    cliente_linux.executar_comando(
        f"docker run --rm "
        f"-v enterprise_certs_volume:/certs "
        f"-v /home/{usuario}/certificadoPix:/from "
        f"busybox sh -c 'rm -f /certs/*.enc'"
    )
    
if(pastaTemporariaItauCerts and os.path.exists(pastaTemporariaItauCerts)):
    try:
        shutil.rmtree(pastaTemporariaItauCerts)
    except Exception as e:
        echo(f"[WARN] Falha ao remover pasta temporária dos certificados Pix: {str(e)}", "info")
try:
        cliente_linux.executar_comando(f'rm -rf /home/{usuario}/certificadoPix')
except Exception as e:
    echo(f"[WARN] Falha ao remover pasta /home/{usuario}/certificadoPix no servidor Linux: {str(e)}", "info")
exit(0)
