"""Tests for data contracts."""

from datetime import datetime

import pytest
from pydantic import ValidationError

from agent_samochodowy.models import MatchResult, Offer, PartQuery, Post


class TestPost:
    def test_valid_post(self):
        p = Post(
            post_id="123",
            group="TIR części",
            author_name="Jan Kowalski",
            author_profile_url="https://facebook.com/jan",
            text="Szukam pompy wody do Volvo FH13",
            timestamp=datetime(2025, 1, 15, 10, 30),
            post_url="https://facebook.com/groups/tir/posts/123",
        )
        assert p.post_id == "123"

    def test_missing_required_field(self):
        with pytest.raises(ValidationError):
            Post(post_id="123", group="g", author_name="a", text="t")  # type: ignore[call-arg]


class TestOffer:
    def test_oe_normalization(self):
        o = Offer(
            offer_id="1",
            platform="allegro",
            url="https://allegro.pl/1",
            title="Pompa wody",
            oe_numbers=["06B 115 105", "a-b.c"],
        )
        assert o.oe_numbers == ["06B115105", "ABC"]

    def test_empty_oe_stripped(self):
        o = Offer(
            offer_id="1",
            platform="ebay",
            url="https://ebay.com/1",
            title="Filter",
            oe_numbers=["ABC", "  ", ""],
        )
        assert o.oe_numbers == ["ABC"]

    def test_invalid_platform(self):
        with pytest.raises(ValidationError):
            Offer(
                offer_id="1",
                platform="amazon",  # type: ignore[arg-type]
                url="u",
                title="t",
            )

    def test_defaults(self):
        o = Offer(offer_id="1", platform="allegro", url="u", title="t")
        assert o.is_part is True
        assert o.qty == 1
        assert o.currency == "PLN"


class TestPartQuery:
    def test_minimal_query(self):
        q = PartQuery(is_part_request=False, raw_text="sprzedam opony")
        assert q.brand is None
        assert q.oe_numbers == []

    def test_oe_normalization(self):
        q = PartQuery(
            is_part_request=True,
            raw_text="szukam",
            oe_numbers=["51.06500-6408"],
        )
        assert q.oe_numbers == ["51065006408"]

    def test_oe_rejects_vin(self):
        """VIN numbers should be filtered out from OE list."""
        q = PartQuery(
            is_part_request=True,
            raw_text="szukam",
            oe_numbers=["WDB96340310075897", "20744939"],
        )
        assert "WDB96340310075897" not in q.oe_numbers
        assert "20744939" in q.oe_numbers

    def test_oe_rejects_postal_code(self):
        """German postal codes like DE59302 should be filtered out."""
        q = PartQuery(
            is_part_request=True,
            raw_text="szukam",
            oe_numbers=["DE59302", "81508206039"],
        )
        assert "DE59302" not in q.oe_numbers
        assert "81508206039" in q.oe_numbers

    def test_oe_keeps_valid_short(self):
        q = PartQuery(
            is_part_request=True,
            raw_text="szukam",
            oe_numbers=["AE4800"],
        )
        assert q.oe_numbers == ["AE4800"]


class TestMatchResult:
    def test_valid_result(self):
        r = MatchResult(confidence=0.95, method="oe", matched=True)
        assert r.offers == []

    def test_confidence_out_of_range(self):
        with pytest.raises(ValidationError):
            MatchResult(confidence=1.5, method="oe")

    def test_negative_confidence(self):
        with pytest.raises(ValidationError):
            MatchResult(confidence=-0.1, method="brak")

    def test_invalid_method(self):
        with pytest.raises(ValidationError):
            MatchResult(confidence=0.5, method="magic")  # type: ignore[arg-type]
