import unittest

from lib.sistemas_docker import (
    SISTEMAS_DOCKER,
    eh_valor_placeholder,
    listar_sistemas_configurados,
    obter_sistema_docker,
    obter_valor_caminho,
)


class TestEhValorPlaceholder(unittest.TestCase):
    def test_marcadores_do_modelo(self):
        for valor in ["VERSAO_ENTERPRISE", "VERSAO_CENTRAL_DE_RELATORIOS", "NAO_DEFINIDO", "HOST"]:
            self.assertTrue(eh_valor_placeholder(valor), valor)

    def test_versoes_reais_e_apelidos_nao_sao_marcadores(self):
        for valor in ["1.6.0", "5.4.9-linux", "master", "latest", "FNX-1234", "1.80", ""]:
            self.assertFalse(eh_valor_placeholder(valor), valor)


class TestObterValorCaminho(unittest.TestCase):
    def test_le_valor_aninhado(self):
        configuracoes = {"a": {"b": {"c": 10}}}

        self.assertEqual(obter_valor_caminho(configuracoes, ("a", "b", "c")), 10)

    def test_caminho_inexistente_retorna_none(self):
        configuracoes = {"a": {"b": 1}}

        self.assertIsNone(obter_valor_caminho(configuracoes, ("a", "x")))
        self.assertIsNone(obter_valor_caminho(configuracoes, ("a", "b", "c")))
        self.assertIsNone(obter_valor_caminho({}, ("a",)))


class TestCatalogoDeSistemas(unittest.TestCase):
    def test_chaves_sao_unicas(self):
        chaves = [sistema.chave for sistema in SISTEMAS_DOCKER]

        self.assertEqual(len(chaves), len(set(chaves)))

    def test_todo_sistema_tem_imagem_fixa_ou_configuravel(self):
        for sistema in SISTEMAS_DOCKER:
            self.assertTrue(
                sistema.imagem or sistema.caminho_imagem,
                f"{sistema.chave} nao declara imagem"
            )

    def test_sistema_desconhecido_gera_erro(self):
        with self.assertRaises(ValueError):
            obter_sistema_docker("sistemaQueNaoExiste")

    def test_enterprise_e_renderizador_sao_fixados_em_linux(self):
        self.assertEqual(obter_sistema_docker("enterprise").obter_plataforma({}), "linux")
        self.assertEqual(obter_sistema_docker("enterpriseRenderizador").obter_plataforma({}), "linux")

    def test_sistemas_sem_plataforma_nao_filtram_tags(self):
        self.assertIsNone(obter_sistema_docker("centralDeRelatorios").obter_plataforma({}))


class TestCredenciaisDoRegistro(unittest.TestCase):
    def test_credencial_especifica_vem_antes_da_geral(self):
        configuracoes = {
            "acessos": {"registroDocker": {"usuario": "oauth2", "senha": "token-geral"}},
            "enterprise": {"imagem": {"usuario": "oauth2", "senha": "token-enterprise"}},
        }

        credenciais = obter_sistema_docker("enterprise").obter_credenciais_registro(configuracoes)

        self.assertEqual(
            credenciais,
            [("oauth2", "token-enterprise"), ("oauth2", "token-geral")]
        )

    def test_credencial_geral_e_alternativa_quando_a_especifica_falha(self):
        # O token especifico da Enterprise costuma estar desatualizado nas
        # configuracoes existentes, por isso a geral precisa ficar na lista.
        configuracoes = {
            "acessos": {"registroDocker": {"usuario": "oauth2", "senha": "token-geral"}},
            "enterprise": {"imagem": {"usuario": "oauth2", "senha": "token-vencido"}},
        }

        credenciais = obter_sistema_docker("enterprise").obter_credenciais_registro(configuracoes)

        self.assertEqual(len(credenciais), 2)
        self.assertIn(("oauth2", "token-geral"), credenciais)

    def test_sem_credencial_especifica_usa_apenas_a_geral(self):
        configuracoes = {
            "acessos": {"registroDocker": {"usuario": "oauth2", "senha": "token-geral"}},
        }

        credenciais = obter_sistema_docker("centralDeRelatorios").obter_credenciais_registro(configuracoes)

        self.assertEqual(credenciais, [("oauth2", "token-geral")])

    def test_credenciais_iguais_nao_sao_duplicadas(self):
        configuracoes = {
            "acessos": {"registroDocker": {"usuario": "oauth2", "senha": "mesmo-token"}},
            "enterprise": {"imagem": {"usuario": "oauth2", "senha": "mesmo-token"}},
        }

        credenciais = obter_sistema_docker("enterprise").obter_credenciais_registro(configuracoes)

        self.assertEqual(credenciais, [("oauth2", "mesmo-token")])


class TestEstaConfigurado(unittest.TestCase):
    def test_exige_servidor_linux_para_sistemas_docker_linux(self):
        configuracoes = {
            "acessos": {"servidorLinux": {"configurar": False}},
            "centralDeRelatorios": {"configurar": True},
        }

        self.assertFalse(obter_sistema_docker("centralDeRelatorios").esta_configurado(configuracoes))

        configuracoes["acessos"]["servidorLinux"]["configurar"] = True

        self.assertTrue(obter_sistema_docker("centralDeRelatorios").esta_configurado(configuracoes))

    def test_monitor_frete_rapido_nao_depende_do_servidor_linux(self):
        configuracoes = {
            "acessos": {"servidorLinux": {"configurar": False}},
            "monitorFreteRapido": {"configurar": True},
        }

        self.assertTrue(obter_sistema_docker("monitorFreteRapido").esta_configurado(configuracoes))

    def test_listar_sistemas_configurados(self):
        configuracoes = {
            "acessos": {"servidorLinux": {"configurar": True}},
            "centralDeRelatorios": {"configurar": True, "storybook": {"configurar": False}},
            "intercompany": {"configurar": True, "storybook": {"configurar": False}},
        }

        chaves = [sistema.chave for sistema in listar_sistemas_configurados(configuracoes)]

        self.assertIn("centralDeRelatorios", chaves)
        self.assertIn("intercompany", chaves)
        self.assertNotIn("centralDeRelatoriosStorybook", chaves)
        self.assertNotIn("enterprise", chaves)


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