"""
Unit tests for app/schemas/request.py — the input validation gate.

These tests matter more than almost any other test in the suite: every
downstream model depends on this validation being correct. A bug here
means bad data silently reaches a model and produces a wrong prediction
with high confidence.
"""

import pytest
from pydantic import ValidationError

from app.schemas.request import CropAnalysisRequest


class TestMonthNormalization:
    def test_accepts_full_month_name(self):
        req = CropAnalysisRequest(crop="rice", location="Thanjavur", month="June")
        assert req.month == 6

    def test_accepts_short_month_name(self):
        req = CropAnalysisRequest(crop="rice", location="Thanjavur", month="Jun")
        assert req.month == 6

    def test_accepts_integer_month(self):
        req = CropAnalysisRequest(crop="rice", location="Thanjavur", month=6)
        assert req.month == 6

    def test_accepts_numeric_string_month(self):
        req = CropAnalysisRequest(crop="rice", location="Thanjavur", month="6")
        assert req.month == 6

    def test_is_case_insensitive(self):
        req = CropAnalysisRequest(crop="rice", location="Thanjavur", month="JUNE")
        assert req.month == 6

    def test_rejects_month_zero(self):
        with pytest.raises(ValidationError):
            CropAnalysisRequest(crop="rice", location="Thanjavur", month=0)

    def test_rejects_month_thirteen(self):
        with pytest.raises(ValidationError):
            CropAnalysisRequest(crop="rice", location="Thanjavur", month=13)

    def test_rejects_invalid_month_name(self):
        with pytest.raises(ValidationError):
            CropAnalysisRequest(crop="rice", location="Thanjavur", month="Smarch")

    def test_rejects_negative_month(self):
        with pytest.raises(ValidationError):
            CropAnalysisRequest(crop="rice", location="Thanjavur", month=-1)


class TestCropAndLocationNormalization:
    def test_strips_and_lowercases_crop(self):
        req = CropAnalysisRequest(crop="  RICE  ", location="Thanjavur", month=6)
        assert req.crop == "rice"

    def test_strips_and_lowercases_location(self):
        req = CropAnalysisRequest(crop="rice", location="  THANJAVUR  ", month=6)
        assert req.location == "thanjavur"

    def test_rejects_empty_crop(self):
        with pytest.raises(ValidationError):
            CropAnalysisRequest(crop="", location="Thanjavur", month=6)

    def test_rejects_whitespace_only_crop(self):
        with pytest.raises(ValidationError):
            CropAnalysisRequest(crop="   ", location="Thanjavur", month=6)

    def test_rejects_too_short_crop(self):
        with pytest.raises(ValidationError):
            CropAnalysisRequest(crop="a", location="Thanjavur", month=6)


class TestRequiredFields:
    def test_missing_crop_raises(self):
        with pytest.raises(ValidationError):
            CropAnalysisRequest(location="Thanjavur", month=6)

    def test_missing_location_raises(self):
        with pytest.raises(ValidationError):
            CropAnalysisRequest(crop="rice", month=6)

    def test_missing_month_raises(self):
        with pytest.raises(ValidationError):
            CropAnalysisRequest(crop="rice", location="Thanjavur")
