import unittest
from types import SimpleNamespace
from unittest.mock import patch
from pathlib import Path
from tempfile import TemporaryDirectory

from lib.ClienteLinux import ClienteLinux, TipoConexao, obter_cliente_linux


class TestClienteLinux(unittest.TestCase):
    def test_traduzir_mensagem_erro_quando_linux_sem_espaco(self):
        cliente_linux = ClienteLinux(TipoConexao.WSL)

        mensagem = cliente_linux._traduzir_mensagem_erro(
            "mkdir: cannot create directory '/tmp/x': No space left on device"
        )

        self.assertIn("Servidor Linux sem espaco em disco.", mensagem)
        self.assertIn("No space left on device", mensagem)

    def test_traduzir_mensagem_erro_quando_cota_de_disco_excedida(self):
        cliente_linux = ClienteLinux(TipoConexao.WSL)

        mensagem = cliente_linux._traduzir_mensagem_erro(
            "cp: error writing '/tmp/y': Disk quota exceeded"
        )

        self.assertIn("Limite de espaco em disco excedido", mensagem)
        self.assertIn("Disk quota exceeded", mensagem)

    def test_traduzir_mensagem_erro_mantem_texto_original_quando_nao_ha_regra(self):
        cliente_linux = ClienteLinux(TipoConexao.WSL)

        mensagem_original = "permission denied"

        self.assertEqual(
            cliente_linux._traduzir_mensagem_erro(mensagem_original),
            mensagem_original
        )

    def test_traduzir_mensagem_erro_quando_put_ssh_grava_zero_bytes(self):
        cliente_linux = ClienteLinux(TipoConexao.WSL)

        mensagem = cliente_linux._traduzir_mensagem_erro(
            "size mismatch in put!  0 != 1250"
        )

        self.assertIn("Falha ao copiar arquivo para o servidor Linux.", mensagem)
        self.assertIn("0 bytes", mensagem)
        self.assertIn("size mismatch in put!  0 != 1250", mensagem)

    @patch("lib.ClienteLinux.time.sleep")
    @patch("lib.ClienteLinux.subprocess.run")
    def test_executar_comando_wsl_preserva_aspas_e_operadores_do_shell(self, subprocess_run_mock, _sleep_mock):
        cliente_linux = ClienteLinux(TipoConexao.WSL)

        subprocess_run_mock.return_value = SimpleNamespace(
            returncode=0,
            stdout=b"ok",
            stderr=b""
        )

        resultado = cliente_linux._executar_comando_wsl(
            "sed -i 's,\\$HOST_ENTERPRISE,10.0.0.1,g' /tmp/api-backends.conf"
        )

        self.assertEqual(resultado.codigo_retorno, 0)
        self.assertEqual(resultado.saida, "ok")
        subprocess_run_mock.assert_called_once_with(
            [
                "wsl",
                "--",
                "sh",
                "-lc",
                "sed -i 's,\\$HOST_ENTERPRISE,10.0.0.1,g' /tmp/api-backends.conf"
            ],
            capture_output=True
        )

    @patch("lib.ClienteLinux.subprocess.run")
    def test_executar_comando_linux_executa_no_shell_local(self, subprocess_run_mock):
        cliente_linux = ClienteLinux(TipoConexao.LINUX)

        subprocess_run_mock.return_value = SimpleNamespace(
            returncode=0,
            stdout="ok",
            stderr=""
        )

        resultado = cliente_linux._executar_comando_linux(
            "sed -i 's,\\$HOST_ENTERPRISE,10.0.0.1,g' /tmp/api-backends.conf"
        )

        self.assertEqual(resultado.codigo_retorno, 0)
        self.assertEqual(resultado.saida, "ok")
        subprocess_run_mock.assert_called_once_with(
            [
                "sh",
                "-lc",
                "sed -i 's,\\$HOST_ENTERPRISE,10.0.0.1,g' /tmp/api-backends.conf"
            ],
            capture_output=True,
            text=True
        )

    def test_obter_cliente_linux_reconhece_tipo_linux(self):
        cliente_linux = obter_cliente_linux(configuracoes={
            "acessos": {
                "servidorLinux": {
                    "tipoConexao": "linux",
                    "host": "localhost",
                    "usuario": "matheussilva",
                    "senha": "NAO_USADA"
                }
            }
        })

        self.assertEqual(cliente_linux.tipo_conexao, TipoConexao.LINUX)
        self.assertEqual(cliente_linux.usuario, "matheussilva")

    @patch("lib.ClienteLinux.echo")
    def test_copiar_arquivo_linux_normaliza_barra_invertida_na_origem(self, _echo_mock):
        cliente_linux = ClienteLinux(TipoConexao.LINUX)

        with TemporaryDirectory() as tmpdir:
            origem = Path(tmpdir) / "origem.txt"
            destino = Path(tmpdir) / "destino" / "arquivo.txt"
            origem.write_text("conteudo", encoding="utf-8")

            cliente_linux.copiar_arquivo(str(origem).replace("/", "\\"), str(destino))

            self.assertEqual(destino.read_text(encoding="utf-8"), "conteudo")


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