import pytest

from datagateway_api.src.common.exceptions import BadRequestError, FilterError
from datagateway_api.src.datagateway_api.filter_order_handler import FilterOrderHandler
from datagateway_api.src.datagateway_api.icat.filters import PythonICATWhereFilter


class TestICATWhereFilter:
    @pytest.mark.parametrize(
        "operation, value, expected_condition_value",
        [
            pytest.param("eq", 5, ["%s = '5'"], id="equal"),
            pytest.param("ne", 5, ["%s != 5"], id="not equal"),
            pytest.param("like", 5, ["%s like '%%5%%'"], id="like"),
            pytest.param("ilike", 5, ["UPPER(%s) like UPPER('%%5%%')"], id="ilike"),
            pytest.param("nlike", 5, ["%s not like '%%5%%'"], id="not like"),
            pytest.param(
                "nilike", 5, ["UPPER(%s) not like UPPER('%%5%%')"], id="not ilike",
            ),
            pytest.param("lt", 5, ["%s < '5'"], id="less than"),
            pytest.param("lte", 5, ["%s <= '5'"], id="less than or equal"),
            pytest.param("gt", 5, ["%s > '5'"], id="greater than"),
            pytest.param("gte", 5, ["%s >= '5'"], id="greater than or equal"),
            pytest.param("in", [1, 2, 3, 4], ["%s in (1, 2, 3, 4)"], id="in a list"),
            pytest.param("in", [], ["%s in (NULL)"], id="empty list"),
        ],
    )
    def test_valid_operations(
        self, icat_query, operation, value, expected_condition_value,
    ):
        test_filter = PythonICATWhereFilter("id", value, operation)
        test_filter.apply_filter(icat_query)

        assert icat_query.conditions == {"id": expected_condition_value}

    def test_invalid_in_operation(self, icat_query):
        with pytest.raises(BadRequestError):
            PythonICATWhereFilter("id", "1, 2, 3, 4, 5", "in")

    def test_invalid_operation(self, icat_query):
        test_filter = PythonICATWhereFilter("id", 10, "non")

        with pytest.raises(FilterError):
            test_filter.apply_filter(icat_query)

    def test_valid_internal_icat_value(self, icat_query):
        """Check that values that point to other values in the schema are applied"""
        test_filter = PythonICATWhereFilter("startDate", "o.endDate", "lt")
        test_filter.apply_filter(icat_query)

        assert icat_query.conditions == {"startDate": ["%s < o.endDate"]}

    def test_valid_field(self, icat_query):
        test_filter = PythonICATWhereFilter("title", "Investigation Title", "eq")
        test_filter.apply_filter(icat_query)

        assert icat_query.conditions == {"title": ["%s = 'Investigation Title'"]}

    def test_invalid_field(self, icat_query):
        test_filter = PythonICATWhereFilter("random_field", "my_value", "eq")

        with pytest.raises(FilterError):
            test_filter.apply_filter(icat_query)

    def test_multiple_conditions_per_field(self, icat_query):
        lt_filter = PythonICATWhereFilter("id", 10, "lt")
        gt_filter = PythonICATWhereFilter("id", 5, "gt")

        filter_handler = FilterOrderHandler()
        filter_handler.add_filters([lt_filter, gt_filter])
        filter_handler.apply_filters(icat_query)

        assert icat_query.conditions == {"id": ["%s < '10'", "%s > '5'"]}

[((1462, 1507), 'datagateway_api.src.datagateway_api.icat.filters.PythonICATWhereFilter', 'PythonICATWhereFilter', (['"""id"""', 'value', 'operation'], {}), "('id', value, operation)\n", (1483, 1507), False, 'from datagateway_api.src.datagateway_api.icat.filters import PythonICATWhereFilter\n'), ((1862, 1900), 'datagateway_api.src.datagateway_api.icat.filters.PythonICATWhereFilter', 'PythonICATWhereFilter', (['"""id"""', '(10)', '"""non"""'], {}), "('id', 10, 'non')\n", (1883, 1900), False, 'from datagateway_api.src.datagateway_api.icat.filters import PythonICATWhereFilter\n'), ((2158, 2211), 'datagateway_api.src.datagateway_api.icat.filters.PythonICATWhereFilter', 'PythonICATWhereFilter', (['"""startDate"""', '"""o.endDate"""', '"""lt"""'], {}), "('startDate', 'o.endDate', 'lt')\n", (2179, 2211), False, 'from datagateway_api.src.datagateway_api.icat.filters import PythonICATWhereFilter\n'), ((2399, 2458), 'datagateway_api.src.datagateway_api.icat.filters.PythonICATWhereFilter', 'PythonICATWhereFilter', (['"""title"""', '"""Investigation Title"""', '"""eq"""'], {}), "('title', 'Investigation Title', 'eq')\n", (2420, 2458), False, 'from datagateway_api.src.datagateway_api.icat.filters import PythonICATWhereFilter\n'), ((2656, 2711), 'datagateway_api.src.datagateway_api.icat.filters.PythonICATWhereFilter', 'PythonICATWhereFilter', (['"""random_field"""', '"""my_value"""', '"""eq"""'], {}), "('random_field', 'my_value', 'eq')\n", (2677, 2711), False, 'from datagateway_api.src.datagateway_api.icat.filters import PythonICATWhereFilter\n'), ((2886, 2923), 'datagateway_api.src.datagateway_api.icat.filters.PythonICATWhereFilter', 'PythonICATWhereFilter', (['"""id"""', '(10)', '"""lt"""'], {}), "('id', 10, 'lt')\n", (2907, 2923), False, 'from datagateway_api.src.datagateway_api.icat.filters import PythonICATWhereFilter\n'), ((2944, 2980), 'datagateway_api.src.datagateway_api.icat.filters.PythonICATWhereFilter', 'PythonICATWhereFilter', (['"""id"""', '(5)', '"""gt"""'], {}), "('id', 5, 'gt')\n", (2965, 2980), False, 'from datagateway_api.src.datagateway_api.icat.filters import PythonICATWhereFilter\n'), ((3007, 3027), 'datagateway_api.src.datagateway_api.filter_order_handler.FilterOrderHandler', 'FilterOrderHandler', ([], {}), '()\n', (3025, 3027), False, 'from datagateway_api.src.datagateway_api.filter_order_handler import FilterOrderHandler\n'), ((400, 447), 'pytest.param', 'pytest.param', (['"""eq"""', '(5)', '["%s = \'5\'"]'], {'id': '"""equal"""'}), '(\'eq\', 5, ["%s = \'5\'"], id=\'equal\')\n', (412, 447), False, 'import pytest\n'), ((461, 511), 'pytest.param', 'pytest.param', (['"""ne"""', '(5)', "['%s != 5']"], {'id': '"""not equal"""'}), "('ne', 5, ['%s != 5'], id='not equal')\n", (473, 511), False, 'import pytest\n'), ((525, 580), 'pytest.param', 'pytest.param', (['"""like"""', '(5)', '["%s like \'%%5%%\'"]'], {'id': '"""like"""'}), '(\'like\', 5, ["%s like \'%%5%%\'"], id=\'like\')\n', (537, 580), False, 'import pytest\n'), ((594, 665), 'pytest.param', 'pytest.param', (['"""ilike"""', '(5)', '["UPPER(%s) like UPPER(\'%%5%%\')"]'], {'id': '"""ilike"""'}), '(\'ilike\', 5, ["UPPER(%s) like UPPER(\'%%5%%\')"], id=\'ilike\')\n', (606, 665), False, 'import pytest\n'), ((679, 743), 'pytest.param', 'pytest.param', (['"""nlike"""', '(5)', '["%s not like \'%%5%%\'"]'], {'id': '"""not like"""'}), '(\'nlike\', 5, ["%s not like \'%%5%%\'"], id=\'not like\')\n', (691, 743), False, 'import pytest\n'), ((757, 842), 'pytest.param', 'pytest.param', (['"""nilike"""', '(5)', '["UPPER(%s) not like UPPER(\'%%5%%\')"]'], {'id': '"""not ilike"""'}), '(\'nilike\', 5, ["UPPER(%s) not like UPPER(\'%%5%%\')"], id=\'not ilike\'\n    )\n', (769, 842), False, 'import pytest\n'), ((882, 933), 'pytest.param', 'pytest.param', (['"""lt"""', '(5)', '["%s < \'5\'"]'], {'id': '"""less than"""'}), '(\'lt\', 5, ["%s < \'5\'"], id=\'less than\')\n', (894, 933), False, 'import pytest\n'), ((947, 1009), 'pytest.param', 'pytest.param', (['"""lte"""', '(5)', '["%s <= \'5\'"]'], {'id': '"""less than or equal"""'}), '(\'lte\', 5, ["%s <= \'5\'"], id=\'less than or equal\')\n', (959, 1009), False, 'import pytest\n'), ((1023, 1077), 'pytest.param', 'pytest.param', (['"""gt"""', '(5)', '["%s > \'5\'"]'], {'id': '"""greater than"""'}), '(\'gt\', 5, ["%s > \'5\'"], id=\'greater than\')\n', (1035, 1077), False, 'import pytest\n'), ((1091, 1156), 'pytest.param', 'pytest.param', (['"""gte"""', '(5)', '["%s >= \'5\'"]'], {'id': '"""greater than or equal"""'}), '(\'gte\', 5, ["%s >= \'5\'"], id=\'greater than or equal\')\n', (1103, 1156), False, 'import pytest\n'), ((1170, 1242), 'pytest.param', 'pytest.param', (['"""in"""', '[1, 2, 3, 4]', "['%s in (1, 2, 3, 4)']"], {'id': '"""in a list"""'}), "('in', [1, 2, 3, 4], ['%s in (1, 2, 3, 4)'], id='in a list')\n", (1182, 1242), False, 'import pytest\n'), ((1256, 1313), 'pytest.param', 'pytest.param', (['"""in"""', '[]', "['%s in (NULL)']"], {'id': '"""empty list"""'}), "('in', [], ['%s in (NULL)'], id='empty list')\n", (1268, 1313), False, 'import pytest\n'), ((1694, 1724), 'pytest.raises', 'pytest.raises', (['BadRequestError'], {}), '(BadRequestError)\n', (1707, 1724), False, 'import pytest\n'), ((1738, 1788), 'datagateway_api.src.datagateway_api.icat.filters.PythonICATWhereFilter', 'PythonICATWhereFilter', (['"""id"""', '"""1, 2, 3, 4, 5"""', '"""in"""'], {}), "('id', '1, 2, 3, 4, 5', 'in')\n", (1759, 1788), False, 'from datagateway_api.src.datagateway_api.icat.filters import PythonICATWhereFilter\n'), ((1915, 1941), 'pytest.raises', 'pytest.raises', (['FilterError'], {}), '(FilterError)\n', (1928, 1941), False, 'import pytest\n'), ((2726, 2752), 'pytest.raises', 'pytest.raises', (['FilterError'], {}), '(FilterError)\n', (2739, 2752), False, 'import pytest\n')]