from __future__ import annotations

from datetime import date

import pytest

from agrobr.normalize.dates import (
    MESES_PT,
    anos_para_safra,
    lista_safras,
    month_to_number,
    normalizar_safra,
    periodo_safra,
    safra_anterior,
    safra_atual,
    safra_para_anos,
    safra_posterior,
    validar_safra,
)


class TestSafraAtual:
    def test_segundo_semestre(self):
        assert safra_atual(date(2024, 10, 15)) == "2024/25"

    def test_primeiro_semestre(self):
        assert safra_atual(date(2025, 3, 15)) == "2024/25"

    def test_julho_inicio_safra(self):
        assert safra_atual(date(2024, 7, 1)) == "2024/25"

    def test_junho_safra_anterior(self):
        assert safra_atual(date(2024, 6, 30)) == "2023/24"

    def test_none_uses_today(self):
        result = safra_atual()
        assert len(result) == 7
        assert "/" in result


class TestValidarSafra:
    def test_formato_padrao(self):
        assert validar_safra("2024/25") is True

    def test_formato_curto(self):
        assert validar_safra("24/25") is True

    def test_formato_completo(self):
        assert validar_safra("2024/2025") is True

    def test_invalido(self):
        assert validar_safra("abc") is False

    def test_vazio(self):
        assert validar_safra("") is False

    def test_apenas_ano(self):
        assert validar_safra("2024") is False


class TestNormalizarSafra:
    def test_padrao_retorna_igual(self):
        assert normalizar_safra("2024/25") == "2024/25"

    def test_curta(self):
        assert normalizar_safra("24/25") == "2024/25"

    def test_completa(self):
        assert normalizar_safra("2024/2025") == "2024/25"

    def test_curta_seculo_anterior(self):
        assert normalizar_safra("99/00") == "1999/00"

    def test_invalido_raises(self):
        with pytest.raises(ValueError, match="inválido"):
            normalizar_safra("abc")

    def test_vazio_raises(self):
        with pytest.raises(ValueError):
            normalizar_safra("")

    def test_espacos_normalizados(self):
        assert normalizar_safra(" 2024 / 25 ") == "2024/25"


class TestSafraParaAnos:
    def test_padrao(self):
        assert safra_para_anos("2024/25") == (2024, 2025)

    def test_curta(self):
        assert safra_para_anos("24/25") == (2024, 2025)

    def test_virada_seculo(self):
        assert safra_para_anos("1999/00") == (1999, 2000)


class TestAnosParaSafra:
    def test_dois_anos(self):
        assert anos_para_safra(2024, 2025) == "2024/25"

    def test_ano_unico(self):
        assert anos_para_safra(2024) == "2024/25"


class TestSafraAnterior:
    def test_uma_safra(self):
        assert safra_anterior("2024/25") == "2023/24"

    def test_tres_safras(self):
        assert safra_anterior("2024/25", 3) == "2021/22"


class TestSafraPosterior:
    def test_uma_safra(self):
        assert safra_posterior("2024/25") == "2025/26"


class TestListaSafras:
    def test_range_5_safras(self):
        result = lista_safras("2020/21", "2024/25")

        assert len(result) == 5
        assert result[0] == "2020/21"
        assert result[-1] == "2024/25"

    def test_mesma_safra(self):
        assert lista_safras("2024/25", "2024/25") == ["2024/25"]


class TestPeriodoSafra:
    def test_periodo(self):
        inicio, fim = periodo_safra("2024/25")

        assert inicio == date(2024, 7, 1)
        assert fim == date(2025, 6, 30)


class TestMesesPt:
    def test_all_12_months_full(self):
        full_names = [
            "janeiro",
            "fevereiro",
            "março",
            "abril",
            "maio",
            "junho",
            "julho",
            "agosto",
            "setembro",
            "outubro",
            "novembro",
            "dezembro",
        ]
        for i, name in enumerate(full_names, 1):
            assert MESES_PT[name] == i

    def test_all_12_months_abbrev(self):
        abbrevs = [
            "jan",
            "fev",
            "mar",
            "abr",
            "mai",
            "jun",
            "jul",
            "ago",
            "set",
            "out",
            "nov",
            "dez",
        ]
        for i, name in enumerate(abbrevs, 1):
            assert MESES_PT[name] == i

    def test_marco_sem_acento(self):
        assert MESES_PT["marco"] == 3


class TestMonthToNumber:
    def test_full_name(self):
        assert month_to_number("janeiro") == 1

    def test_abbreviation(self):
        assert month_to_number("jan") == 1

    def test_case_insensitive(self):
        assert month_to_number("JANEIRO") == 1
        assert month_to_number("JAN") == 1

    def test_whitespace(self):
        assert month_to_number("  março  ") == 3

    def test_unknown_returns_none(self):
        assert month_to_number("xyz") is None

    def test_accented(self):
        assert month_to_number("março") == 3

    def test_unaccented_variant(self):
        assert month_to_number("marco") == 3
