import unittest

from lib.hard_reset_linux import executar_hard_reset_linux


COMANDO_DOWN_COMPOSES_DEPLOY = (
    "find /home/deploy -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"
)


class ClienteLinuxFake:
    def __init__(self, codigos_retorno=None, saidas=None):
        self.comandos = []
        self.codigos_retorno = list(codigos_retorno or [])
        self.saidas = list(saidas or [])

    def executar_comando(self, comando, disparar_excecao_se_retorno_nao_zero=True, echoar=True, descricao=""):
        self.comandos.append((comando, disparar_excecao_se_retorno_nao_zero))
        codigo_retorno = self.codigos_retorno.pop(0) if self.codigos_retorno else 0
        saida = self.saidas.pop(0) if self.saidas else ""

        class ResultadoFake:
            def __init__(self, codigo_retorno, saida):
                self.codigo_retorno = codigo_retorno
                self.saida = saida

        return ResultadoFake(codigo_retorno, saida)


class TestHardResetLinux(unittest.TestCase):
    def test_executar_hard_reset_linux_para_containers_prune_e_apaga_home(self):
        cliente_linux = ClienteLinuxFake()

        executar_hard_reset_linux(cliente_linux, "deploy")

        self.assertEqual(
            cliente_linux.comandos,
            [
                (COMANDO_DOWN_COMPOSES_DEPLOY, False),
                ("docker ps -q | xargs -r docker stop", False),
                ("docker ps -aq | xargs -r docker rm -f", False),
                ("find /home/deploy -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +", False),
                ("docker system prune -af --volumes", False),
                ("docker volume ls -q", False),
            ]
        )

    def test_executar_hard_reset_linux_usa_docker_quando_usuario_nao_consegue_apagar_home(self):
        cliente_linux = ClienteLinuxFake(codigos_retorno=[0, 0, 0, 1, 0, 0])

        executar_hard_reset_linux(cliente_linux, "deploy")

        self.assertEqual(
            cliente_linux.comandos,
            [
                (COMANDO_DOWN_COMPOSES_DEPLOY, False),
                ("docker ps -q | xargs -r docker stop", False),
                ("docker ps -aq | xargs -r docker rm -f", False),
                ("find /home/deploy -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +", False),
                (
                    "docker run --rm -v /home/deploy:/home-hard-reset alpine:3.20 sh -c "
                    "'find /home-hard-reset -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +'",
                    True
                ),
                ("docker system prune -af --volumes", False),
                ("docker volume ls -q", False),
            ]
        )

    def test_executar_hard_reset_linux_bloqueia_usuario_invalido(self):
        cliente_linux = ClienteLinuxFake()

        with self.assertRaises(ValueError):
            executar_hard_reset_linux(cliente_linux, "../deploy")

        self.assertEqual(cliente_linux.comandos, [])

    def test_executar_hard_reset_linux_remove_volumes_listados(self):
        cliente_linux = ClienteLinuxFake(
            saidas=["", "", "", "", "", "volume_um\nvolume dois\n"]
        )

        executar_hard_reset_linux(cliente_linux, "deploy")

        self.assertEqual(
            cliente_linux.comandos[-3:],
            [
                ("docker volume ls -q", False),
                ("docker volume rm -f volume_um", False),
                ("docker volume rm -f 'volume dois'", False),
            ]
        )


if __name__ == "__main__":
    unittest.main()
