"""Tests for caffeinate_me.coffee_types."""

import pytest

from caffeinate_me.coffee_types import (
    COFFEE_TYPES,
    get_all_types,
    get_coffee_info,
    get_recommendation,
)

_REQUIRED_FIELDS = ["name", "emoji", "caffeine_mg", "description", "brew_time", "intensity"]
_VALID_INTENSITIES = {"mild", "strong", "espresso"}


class TestCoffeeTypes:
    def test_at_least_five_types(self):
        assert len(COFFEE_TYPES) >= 5

    def test_espresso_present(self):
        assert "espresso" in COFFEE_TYPES

    def test_all_have_required_fields(self):
        for key, info in COFFEE_TYPES.items():
            for field in _REQUIRED_FIELDS:
                assert field in info, f"'{key}' is missing field '{field}'"

    def test_caffeine_is_positive(self):
        for key, info in COFFEE_TYPES.items():
            assert info["caffeine_mg"] > 0, f"'{key}' has non-positive caffeine_mg"

    def test_valid_intensity_values(self):
        for key, info in COFFEE_TYPES.items():
            assert info["intensity"] in _VALID_INTENSITIES, (
                f"'{key}' has unrecognised intensity '{info['intensity']}'"
            )

    def test_brew_seconds_positive(self):
        for key, info in COFFEE_TYPES.items():
            assert info.get("brew_seconds", 1) > 0


class TestGetCoffeeInfo:
    def test_known_type_returns_dict(self):
        info = get_coffee_info("espresso")
        assert info is not None
        assert info["name"] == "Espresso"

    def test_unknown_type_returns_none(self):
        assert get_coffee_info("unicorn_latte") is None

    @pytest.mark.parametrize("key", list(COFFEE_TYPES.keys()))
    def test_all_types_retrievable(self, key):
        assert get_coffee_info(key) is not None


class TestGetRecommendation:
    def test_returns_coffee_dict(self):
        rec = get_recommendation()
        assert isinstance(rec, dict)
        assert "name" in rec
        assert "caffeine_mg" in rec

    @pytest.mark.parametrize("intensity", ["mild", "strong", "espresso"])
    def test_intensity_filter_respected(self, intensity):
        # Run several times to account for randomness.
        for _ in range(20):
            rec = get_recommendation(intensity=intensity)
            assert rec["intensity"] == intensity

    def test_no_intensity_still_returns_valid(self):
        rec = get_recommendation(intensity=None)
        assert rec["intensity"] in _VALID_INTENSITIES


class TestGetAllTypes:
    def test_returns_list(self):
        assert isinstance(get_all_types(), list)

    def test_all_keys_in_coffee_types(self):
        for t in get_all_types():
            assert t in COFFEE_TYPES
