"""Collection of tests to ensure correct handling of invalid input."""

from fastapi.testclient import TestClient
import pytest

from ..main import app


@pytest.fixture(scope="module")
def invalid_client():
    """Client used to call the app."""
    return TestClient(app)


@pytest.mark.parametrize(
    "start,preferences,status_code",
    [
        # Invalid case: no preferences at all.
        ([48.8566, 2.3522], {}, 422),

        # Invalid cases: incomplete preferences.
        ([48.084588, 7.280405], {"sightseeing": {"type": "sightseeing", "score": 5},    # no shopping pref
                                 "nature": {"type": "nature", "score": 5},
                                 }, 422),
        ([48.084588, 7.280405], {"sightseeing": {"type": "sightseeing", "score": 5},    # no nature pref
                                 "shopping": {"type": "shopping", "score": 5},
                                 }, 422),
        ([48.084588, 7.280405], {"nature": {"type": "nature", "score": 5},              # no sightseeing pref
                                 "shopping": {"type": "shopping", "score": 5},
                                 }, 422),
        ([48.084588, 7.280405], {"sightseeing": {"type": "nature", "score": 1},         # mixed up preferences types. TODO: i suggest reducing the complexity by remove the Preference object.
                                 "nature": {"type": "shopping", "score": 1},
                                 "shopping": {"type": "shopping", "score": 1},
                                 }, 422),
        ([48.084588, 7.280405], {"doesnotexist": {"type": "sightseeing", "score": 2},   # non-existing preferences types
                                 "nature": {"type": "nature", "score": 2},
                                 "shopping": {"type": "shopping", "score": 2},
                                 }, 422),
        ([48.084588, 7.280405], {"sightseeing": {"type": "sightseeing", "score": 3},    # non-existing preferences types
                                 "nature": {"type": "doesntexisteither", "score": 3},
                                 "shopping": {"type": "shopping", "score": 3},
                                 }, 422),
        ([48.084588, 7.280405], {"sightseeing": {"type": "sightseeing", "score": -1},   # negative preference value
                                 "nature": {"type": "doesntexisteither", "score": 4},
                                 "shopping": {"type": "shopping", "score": 4},
                                 }, 422),
        ([48.084588, 7.280405], {"sightseeing": {"type": "sightseeing", "score": 10},   # too high preference value
                                 "nature": {"type": "doesntexisteither", "score": 4},
                                 "shopping": {"type": "shopping", "score": 4},
                                 }, 422),

        # Invalid cases: unexisting coords
        ([91, 181], {"sightseeing": {"type": "sightseeing", "score": 5},
                     "nature": {"type": "nature", "score": 5},
                     "shopping": {"type": "shopping", "score": 5},
                    }, 422),
        ([-91, 181], {"sightseeing": {"type": "sightseeing", "score": 5},
                     "nature": {"type": "nature", "score": 5},
                     "shopping": {"type": "shopping", "score": 5},
                    }, 422),
        ([91, -181], {"sightseeing": {"type": "sightseeing", "score": 5},
                     "nature": {"type": "nature", "score": 5},
                     "shopping": {"type": "shopping", "score": 5},
                    }, 422),
        ([-91, -181], {"sightseeing": {"type": "sightseeing", "score": 5},
                     "nature": {"type": "nature", "score": 5},
                     "shopping": {"type": "shopping", "score": 5},
                    }, 422),
    ]
)
def test_input(invalid_client, start, preferences, status_code):   # pylint: disable=redefined-outer-name
    """
    Test new trip creation with different sets of preferences and locations.
    """
    response = invalid_client.post(
        "/get/landmarks",
        json ={
            "preferences": preferences,
            "start": start
        }
    )
    assert response.status_code == status_code
