"""Testes para o parser do Notícias Agrícolas."""

from datetime import date
from decimal import Decimal

import pytest

from agrobr.constants import Fonte
from agrobr.noticias_agricolas.parser import (
    PRACAS,
    UNIDADES,
    _parse_date,
    _parse_valor,
    _parse_variacao,
    parse_indicador,
)


class TestParseFunctions:
    """Testes para funções auxiliares de parse."""

    def test_parse_date_valid(self):
        """Testa parse de data válida."""
        result = _parse_date("03/02/2026")
        assert result is not None
        assert result.day == 3
        assert result.month == 2
        assert result.year == 2026

    def test_parse_date_invalid(self):
        """Testa parse de data inválida."""
        assert _parse_date("invalid") is None
        assert _parse_date("32/13/2026") is None
        assert _parse_date("") is None

    def test_parse_valor_valid(self):
        """Testa parse de valor válido."""
        assert _parse_valor("124,55") == Decimal("124.55")
        assert _parse_valor("1.234,56") == Decimal("1234.56")
        assert _parse_valor("R$ 124,55") == Decimal("124.55")
        assert _parse_valor("  124,55  ") == Decimal("124.55")

    def test_parse_valor_invalid(self):
        """Testa parse de valor inválido."""
        assert _parse_valor("invalid") is None
        assert _parse_valor("") is None

    def test_parse_variacao_valid(self):
        """Testa parse de variação válida."""
        assert _parse_variacao("-0,26") == Decimal("-0.26")
        assert _parse_variacao("+0,16") == Decimal("0.16")
        assert _parse_variacao("0,23%") == Decimal("0.23")
        assert _parse_variacao("-0,26%") == Decimal("-0.26")

    def test_parse_variacao_invalid(self):
        """Testa parse de variação inválida."""
        assert _parse_variacao("invalid") is None
        assert _parse_variacao("") is None


class TestParseIndicador:
    """Testes para parse_indicador."""

    @pytest.fixture
    def sample_html(self):
        """HTML de exemplo com tabela de cotações."""
        return """
        <html>
        <body>
        <table class="cot-fisicas">
            <thead>
                <tr>
                    <th>Data</th>
                    <th>Valor R$</th>
                    <th>Variação (%)</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>03/02/2026</td>
                    <td>124,55</td>
                    <td>-0,26</td>
                </tr>
                <tr>
                    <td>02/02/2026</td>
                    <td>124,88</td>
                    <td>-0,02</td>
                </tr>
            </tbody>
        </table>
        </body>
        </html>
        """

    def test_parse_indicador_success(self, sample_html):
        """Testa parse bem-sucedido."""
        indicadores = parse_indicador(sample_html, "soja")

        assert len(indicadores) == 2

        # Primeiro indicador
        ind1 = indicadores[0]
        assert ind1.fonte == Fonte.NOTICIAS_AGRICOLAS
        assert ind1.produto == "soja"
        assert ind1.data == date(2026, 2, 3)
        assert ind1.valor == Decimal("124.55")
        assert ind1.unidade == "BRL/sc60kg"
        assert ind1.praca == "Paranaguá/PR"
        assert ind1.meta["variacao_percentual"] == -0.26
        assert ind1.meta["fonte_original"] == "CEPEA/ESALQ"

        # Segundo indicador
        ind2 = indicadores[1]
        assert ind2.data == date(2026, 2, 2)
        assert ind2.valor == Decimal("124.88")

    def test_parse_indicador_empty_html(self):
        """Testa parse com HTML vazio."""
        indicadores = parse_indicador("<html></html>", "soja")
        assert len(indicadores) == 0

    def test_parse_indicador_no_table(self):
        """Testa parse sem tabela de cotações."""
        html = "<html><body><p>Sem tabela</p></body></html>"
        indicadores = parse_indicador(html, "soja")
        assert len(indicadores) == 0

    def test_parse_indicador_different_products(self, sample_html):
        """Testa parse para diferentes produtos."""
        for produto in ["soja", "milho", "boi", "cafe"]:
            indicadores = parse_indicador(sample_html, produto)
            assert len(indicadores) == 2
            assert indicadores[0].produto == produto
            assert indicadores[0].unidade == UNIDADES[produto]
            assert indicadores[0].praca == PRACAS[produto]


class TestConstants:
    """Testes para constantes do parser."""

    def test_unidades_mapping(self):
        """Verifica mapeamento de unidades."""
        assert UNIDADES["soja"] == "BRL/sc60kg"
        assert UNIDADES["milho"] == "BRL/sc60kg"
        assert UNIDADES["boi"] == "BRL/@"
        assert UNIDADES["cafe"] == "BRL/sc60kg"
        assert UNIDADES["algodao"] == "BRL/@"
        assert UNIDADES["trigo"] == "BRL/ton"

    def test_pracas_mapping(self):
        """Verifica mapeamento de praças."""
        assert PRACAS["soja"] == "Paranaguá/PR"
        assert PRACAS["milho"] == "Campinas/SP"
        assert PRACAS["boi"] == "São Paulo/SP"
        assert PRACAS["cafe"] == "São Paulo/SP"
