"""
Unit tests for app/services/reference_data.py.

Tests use a temp directory with controlled JSON fixtures rather than
the real data/lookup files, so these tests stay independent of
whatever crops/districts happen to be configured for the live client
deployment.
"""

import json

import pytest

from app.core.exceptions import UnsupportedCropError, UnsupportedDistrictError
from app.services.reference_data import ReferenceDataService


@pytest.fixture
def populated_service(tmp_path, sample_crops_lookup, sample_districts_lookup, monkeypatch):
    lookup_dir = tmp_path / "lookup"
    lookup_dir.mkdir()
    (lookup_dir / "crops.json").write_text(json.dumps(sample_crops_lookup))
    (lookup_dir / "districts.json").write_text(json.dumps(sample_districts_lookup))

    import app.services.reference_data as module
    monkeypatch.setattr(module, "LOOKUP_DIR", lookup_dir)

    service = ReferenceDataService()
    service.load()
    return service


class TestReferenceDataService:
    def test_load_succeeds_with_valid_files(self, populated_service):
        assert populated_service._loaded is True

    def test_get_crop_returns_properties(self, populated_service):
        props = populated_service.get_crop("rice")
        assert props["water_req_mm"] == 1200

    def test_get_crop_is_case_insensitive(self, populated_service):
        props = populated_service.get_crop("RICE")
        assert props["water_req_mm"] == 1200

    def test_get_crop_raises_for_unknown_crop(self, populated_service):
        with pytest.raises(UnsupportedCropError):
            populated_service.get_crop("dragonfruit")

    def test_get_district_returns_properties(self, populated_service):
        props = populated_service.get_district("thanjavur")
        assert props["state"] == "tamil nadu"

    def test_get_district_raises_for_unknown_district(self, populated_service):
        with pytest.raises(UnsupportedDistrictError):
            populated_service.get_district("atlantis")

    def test_list_crops_returns_sorted_list(self, populated_service):
        assert populated_service.list_crops() == ["maize", "rice"]

    def test_list_districts_returns_sorted_list(self, populated_service):
        assert populated_service.list_districts() == ["madurai", "thanjavur"]

    def test_is_valid_crop_true_case(self, populated_service):
        assert populated_service.is_valid_crop("rice") is True

    def test_is_valid_crop_false_case(self, populated_service):
        assert populated_service.is_valid_crop("dragonfruit") is False

    def test_using_before_load_raises(self):
        service = ReferenceDataService()
        with pytest.raises(RuntimeError):
            service.get_crop("rice")

    def test_missing_crops_file_raises(self, tmp_path, monkeypatch):
        lookup_dir = tmp_path / "empty_lookup"
        lookup_dir.mkdir()
        (lookup_dir / "districts.json").write_text("{}")

        import app.services.reference_data as module
        monkeypatch.setattr(module, "LOOKUP_DIR", lookup_dir)

        service = ReferenceDataService()
        with pytest.raises(FileNotFoundError):
            service.load()

    def test_empty_crops_file_raises(self, tmp_path, monkeypatch):
        lookup_dir = tmp_path / "lookup_empty_crops"
        lookup_dir.mkdir()
        (lookup_dir / "crops.json").write_text("{}")
        (lookup_dir / "districts.json").write_text('{"thanjavur": {}}')

        import app.services.reference_data as module
        monkeypatch.setattr(module, "LOOKUP_DIR", lookup_dir)

        service = ReferenceDataService()
        with pytest.raises(ValueError):
            service.load()
