from shlex import quote

from lib.echo import echo


def validar_usuario_home(usuario):
    if not usuario or "/" in usuario or usuario in [".", ".."]:
        raise ValueError(f"Usuario Linux invalido para hard reset: {usuario}")


def parar_todos_containers(cliente_linux):
    echo("Parando todos os containers Docker")
    cliente_linux.executar_comando(
        "docker ps -q | xargs -r docker stop",
        disparar_excecao_se_retorno_nao_zero=False
    )


def remover_todos_containers(cliente_linux):
    echo("Removendo todos os containers Docker")
    cliente_linux.executar_comando(
        "docker ps -aq | xargs -r docker rm -f",
        disparar_excecao_se_retorno_nao_zero=False
    )


def executar_down_composes_home_usuario(cliente_linux, usuario):
    caminho_home = quote(f"/home/{usuario}")
    comando = (
        f"find {caminho_home} -mindepth 2 -maxdepth 3 "
        r"\( -name 'docker-compose.yml' -o -name 'docker-compose-*.yml' \) "
        r"-print0 | xargs -0 -r -I {} docker compose -f {} down --remove-orphans"
    )

    echo(f"Executando docker compose down --remove-orphans nos composes de /home/{usuario}")
    cliente_linux.executar_comando(
        comando,
        disparar_excecao_se_retorno_nao_zero=False
    )


def executar_docker_system_prune(cliente_linux):
    echo("Executando docker system prune (removendo containers parados, redes, imagens e volumes nao utilizados)")
    cliente_linux.executar_comando(
        "docker system prune -af --volumes",
        disparar_excecao_se_retorno_nao_zero=False
    )


def remover_todos_volumes_docker(cliente_linux):
    echo("Listando volumes Docker existentes")
    resultado = cliente_linux.executar_comando(
        "docker volume ls -q",
        disparar_excecao_se_retorno_nao_zero=False
    )

    if resultado.codigo_retorno != 0:
        echo("Falha ao listar volumes Docker. Pulando remocao nominal de volumes", "error")
        return

    volumes = [linha.strip() for linha in resultado.saida.splitlines() if linha.strip()]

    if not volumes:
        echo("Nenhum volume Docker encontrado para remover")
        return

    echo(f"Foram encontrados {len(volumes)} volume(s) Docker. Removendo um a um")

    for volume in volumes:
        echo(f"Removendo volume Docker: {volume}")
        resultado_remocao = cliente_linux.executar_comando(
            f"docker volume rm -f {quote(volume)}",
            disparar_excecao_se_retorno_nao_zero=False
        )

        if resultado_remocao.codigo_retorno != 0:
            echo(f"Falha ao remover volume Docker: {volume}", "error")


def obter_comando_remocao_conteudo(diretorio):
    return f"find {diretorio} -mindepth 1 -maxdepth 1 -exec rm -rf -- {{}} +"


def remover_conteudo_home_usuario_com_docker(cliente_linux, usuario):
    caminho_home = quote(f"/home/{usuario}")
    diretorio_container = "/home-hard-reset"
    comando_remocao = obter_comando_remocao_conteudo(diretorio_container)

    echo(f"Removendo todo o conteudo dentro de /home/{usuario} usando container auxiliar")
    cliente_linux.executar_comando(
        "docker run --rm "
        f"-v {caminho_home}:{diretorio_container} "
        f"alpine:3.20 sh -c {quote(comando_remocao)}"
    )


def remover_conteudo_home_usuario(cliente_linux, usuario):
    caminho_home = quote(f"/home/{usuario}")

    echo(f"Removendo todo o conteudo dentro de /home/{usuario}")
    resultado = cliente_linux.executar_comando(
        obter_comando_remocao_conteudo(caminho_home),
        disparar_excecao_se_retorno_nao_zero=False
    )

    if resultado.codigo_retorno == 0:
        return

    echo("Falha ao remover com o usuario Linux. Tentando remover usando Docker")
    remover_conteudo_home_usuario_com_docker(cliente_linux, usuario)


def executar_hard_reset_linux(cliente_linux, usuario):
    validar_usuario_home(usuario)
    executar_down_composes_home_usuario(cliente_linux, usuario)
    parar_todos_containers(cliente_linux)
    remover_todos_containers(cliente_linux)
    remover_conteudo_home_usuario(cliente_linux, usuario)
    executar_docker_system_prune(cliente_linux)
    remover_todos_volumes_docker(cliente_linux)
