import unittest

from lib.versoes_docker import (
    analisar_versao,
    comparar_versoes,
    eh_referencia_versao_mais_recente,
    ordenar_tags_da_mais_recente_para_mais_antiga,
    pode_comparar_com_versao_minima,
    selecionar_versao_oficial_mais_recente,
    versao_maior_ou_igual,
)


class TestEhReferenciaVersaoMaisRecente(unittest.TestCase):
    def test_reconhece_master_em_qualquer_caixa(self):
        self.assertTrue(eh_referencia_versao_mais_recente("master"))
        self.assertTrue(eh_referencia_versao_mais_recente("MASTER"))
        self.assertTrue(eh_referencia_versao_mais_recente("  Master  "))

    def test_reconhece_outros_apelidos(self):
        self.assertTrue(eh_referencia_versao_mais_recente("main"))
        self.assertTrue(eh_referencia_versao_mais_recente("latest"))

    def test_nao_reconhece_versao_concreta(self):
        self.assertFalse(eh_referencia_versao_mais_recente("1.6.0"))
        self.assertFalse(eh_referencia_versao_mais_recente("5.4.9-linux"))
        self.assertFalse(eh_referencia_versao_mais_recente(""))
        self.assertFalse(eh_referencia_versao_mais_recente(None))


class TestAnalisarVersao(unittest.TestCase):
    def test_versao_oficial_pura(self):
        versao = analisar_versao("1.6.0")

        self.assertEqual(versao.numeros, (1, 6, 0))
        self.assertEqual(versao.sufixo, "")
        self.assertTrue(versao.eh_versao_oficial)
        self.assertFalse(versao.eh_pre_lancamento)

    def test_versao_oficial_com_sufixo_de_plataforma(self):
        versao = analisar_versao("5.4.9-linux")

        self.assertEqual(versao.numeros, (5, 4, 9))
        self.assertTrue(versao.eh_versao_oficial)
        self.assertTrue(versao.tem_plataforma("linux"))
        self.assertFalse(versao.tem_plataforma("windows"))

    def test_versao_com_plataforma_composta(self):
        versao = analisar_versao("1.4.2-windows-2016")

        self.assertTrue(versao.eh_versao_oficial)
        self.assertTrue(versao.tem_plataforma("windows"))

    def test_versao_de_dois_componentes(self):
        versao = analisar_versao("1.80")

        self.assertEqual(versao.numeros, (1, 80))
        self.assertTrue(versao.eh_versao_oficial)

    def test_pre_lancamento_nao_e_versao_oficial(self):
        for tag in ["0.9-beta", "1.6.0-rc1", "2.0.0-alpha.2", "1.0.0-snapshot"]:
            self.assertFalse(analisar_versao(tag).eh_versao_oficial, tag)
            self.assertTrue(analisar_versao(tag).eh_pre_lancamento, tag)

    def test_tag_de_branch_nao_e_versao_oficial(self):
        for tag in ["FNX-5220-windows", "master", "476443-Centaurus-ContasAReceber"]:
            self.assertFalse(analisar_versao(tag).eh_versao_oficial, tag)


class TestCompararVersoes(unittest.TestCase):
    def test_ordem_pedida_pelo_usuario(self):
        # 1.80 e mais atualizada que 1.7.0 e que 0.9-beta
        self.assertEqual(comparar_versoes("1.80", "1.7.0"), 1)
        self.assertEqual(comparar_versoes("1.80", "0.9-beta"), 1)
        self.assertEqual(comparar_versoes("1.7.0", "0.9-beta"), 1)

    def test_comparacao_numerica_por_componente(self):
        self.assertEqual(comparar_versoes("5.5.0", "5.4.9"), 1)
        self.assertEqual(comparar_versoes("5.4.9", "5.5.0"), -1)
        self.assertEqual(comparar_versoes("5.4.10", "5.4.9"), 1)

    def test_sufixo_de_plataforma_nao_muda_precedencia(self):
        self.assertEqual(comparar_versoes("5.4.9-linux", "5.4.9"), 0)
        self.assertEqual(comparar_versoes("5.4.9-linux", "5.4.9-windows"), 0)

    def test_componentes_ausentes_valem_zero(self):
        self.assertEqual(comparar_versoes("1.6", "1.6.0"), 0)
        self.assertEqual(comparar_versoes("2", "2.0.0"), 0)

    def test_pre_lancamento_vale_menos_que_versao_final(self):
        self.assertEqual(comparar_versoes("1.6.0-rc1", "1.6.0"), -1)
        self.assertEqual(comparar_versoes("0.9", "0.9-beta"), 1)

    def test_versao_numerica_vale_mais_que_tag_de_branch(self):
        self.assertEqual(comparar_versoes("1.4.2-windows-2016", "FNX-5220-windows"), 1)
        self.assertEqual(comparar_versoes("FNX-5220-windows", "1.4.2-windows-2016"), -1)

    def test_versao_maior_ou_igual(self):
        self.assertTrue(versao_maior_ou_igual("5.4.9-linux", "5.4.9"))
        self.assertTrue(versao_maior_ou_igual("5.5.0-linux", "5.4.9"))
        self.assertFalse(versao_maior_ou_igual("5.4.7-linux", "5.4.9"))
        self.assertTrue(versao_maior_ou_igual("1.6.0", "1.6.0"))
        self.assertFalse(versao_maior_ou_igual("1.5.0", "1.6.0"))


class TestPodeCompararComVersaoMinima(unittest.TestCase):
    def test_versao_numerica_pode_ser_comparada(self):
        self.assertTrue(pode_comparar_com_versao_minima("5.4.9-linux"))
        self.assertTrue(pode_comparar_com_versao_minima("0.9-beta"))

    def test_tag_de_branch_nao_pode_ser_comparada(self):
        self.assertFalse(pode_comparar_com_versao_minima("FNX-1234"))
        self.assertFalse(pode_comparar_com_versao_minima("master"))

    def test_branch_de_ficha_nao_pode_ser_comparada(self):
        """
        Branch de ficha comeca com o numero da ficha, que e maior que qualquer
        versao real: comparar 493081 com a versao minima da regra faria o mapa de
        dependencias cobrar (ou liberar) regra que nao tem como avaliar.
        """

        self.assertFalse(pode_comparar_com_versao_minima("493081_junio_SacolaAdicionarProduto_Predial"))
        self.assertFalse(pode_comparar_com_versao_minima("491925_liberacao_desconto"))
        self.assertFalse(pode_comparar_com_versao_minima("Matheus_PA_492055_PixAPrazoWhatsapp"))


class TestSelecionarVersaoOficialMaisRecente(unittest.TestCase):
    def test_ignora_branch_e_pre_lancamento(self):
        tags = ["1.7.0", "1.80", "0.9-beta", "master", "FNX-5220-windows", "2.0.0-alpha.2"]

        self.assertEqual(selecionar_versao_oficial_mais_recente(tags), "1.80")

    def test_filtra_por_plataforma(self):
        tags = ["5.4.9-linux", "5.5.0-windows", "5.4.8-linux", "master"]

        self.assertEqual(
            selecionar_versao_oficial_mais_recente(tags, plataforma="linux"),
            "5.4.9-linux"
        )
        self.assertEqual(
            selecionar_versao_oficial_mais_recente(tags, plataforma="windows"),
            "5.5.0-windows"
        )

    def test_retorna_none_quando_nao_ha_versao_oficial(self):
        self.assertIsNone(selecionar_versao_oficial_mais_recente(["master", "FNX-1"]))
        self.assertIsNone(selecionar_versao_oficial_mais_recente([]))
        self.assertIsNone(selecionar_versao_oficial_mais_recente(None))

    def test_retorna_none_quando_plataforma_nao_existe(self):
        self.assertIsNone(
            selecionar_versao_oficial_mais_recente(["1.0.0-windows"], plataforma="linux")
        )

    def test_cenario_real_central_de_relatorios(self):
        tags = [
            "476443-Centaurus-ContasAReceber", "1.6.0", "1.5.0", "1.4.4",
            "1.4.3", "1.4.2", "1.4.1", "1.4.0", "1.3.0", "1.2.3",
        ]

        self.assertEqual(selecionar_versao_oficial_mais_recente(tags), "1.6.0")

    def test_cenario_real_enterprise_linux(self):
        tags = [
            "490764-pix-prazo-email-html-qrcode",
            "490764-pix-prazo-email-html-qrcode-linux",
            "5.4.9-linux", "5.4.7-linux", "5.4.5-linux", "5.4.4-linux",
        ]

        self.assertEqual(
            selecionar_versao_oficial_mais_recente(tags, plataforma="linux"),
            "5.4.9-linux"
        )


class TestOrdenarTags(unittest.TestCase):
    def test_ordena_da_mais_recente_para_mais_antiga(self):
        tags = ["1.4.0", "1.80", "0.9-beta", "1.7.0"]

        self.assertEqual(
            ordenar_tags_da_mais_recente_para_mais_antiga(tags),
            ["1.80", "1.7.0", "1.4.0", "0.9-beta"]
        )

    def test_tags_de_branch_ficam_no_final(self):
        resultado = ordenar_tags_da_mais_recente_para_mais_antiga(["master", "1.0.0", "FNX-1"])

        self.assertEqual(resultado[0], "1.0.0")

    def test_betas_da_central_de_relatorios_ficam_no_bloco_das_versoes(self):
        """
        Antes da 1.0.0 as betas eram o release oficial da Central de Relatorios:
        precisam aparecer ordenadas pelo numero, e nao junto das branches.
        """

        tags = ["0.2.0-beta", "1.0.0", "0.4.0-beta", "1.1.0", "0.1.0-beta", "1.0.1", "0.3.0-beta", "master"]

        self.assertEqual(
            ordenar_tags_da_mais_recente_para_mais_antiga(tags),
            ["1.1.0", "1.0.1", "1.0.0", "0.4.0-beta", "0.3.0-beta", "0.2.0-beta", "0.1.0-beta", "master"]
        )

    def test_branch_de_ficha_fica_abaixo_da_versao_oficial(self):
        tags = [
            "493081_junio_SacolaAdicionarProduto_Predial",
            "5.111.2",
            "492914_marcio_MenuProdutoForaOrc_Tresmacol",
            "5.109.0",
        ]

        self.assertEqual(
            ordenar_tags_da_mais_recente_para_mais_antiga(tags),
            [
                "5.111.2",
                "5.109.0",
                "493081_junio_SacolaAdicionarProduto_Predial",
                "492914_marcio_MenuProdutoForaOrc_Tresmacol",
            ]
        )


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