from pandagg.query import (
    Intervals,
    Match,
    MatchBoolPrefix,
    MatchPhrase,
    MatchPhrasePrefix,
    MultiMatch,
    QueryString,
    SimpleQueryString,
)


def test_interval_clause():
    body = {
        "some_field": {
            "all_of": {
                "intervals": [
                    {"match": {"query": "the"}},
                    {
                        "any_of": {
                            "intervals": [
                                {"match": {"query": "big"}},
                                {"match": {"query": "big bad"}},
                            ]
                        }
                    },
                    {"match": {"query": "wolf"}},
                ],
                "max_gaps": 0,
                "ordered": True,
            }
        }
    }
    expected = {"intervals": body}

    q1 = Intervals(
        field="some_field",
        all_of={
            "intervals": [
                {"match": {"query": "the"}},
                {
                    "any_of": {
                        "intervals": [
                            {"match": {"query": "big"}},
                            {"match": {"query": "big bad"}},
                        ]
                    }
                },
                {"match": {"query": "wolf"}},
            ],
            "max_gaps": 0,
            "ordered": True,
        },
    )
    q2 = Intervals(
        some_field={
            "all_of": {
                "intervals": [
                    {"match": {"query": "the"}},
                    {
                        "any_of": {
                            "intervals": [
                                {"match": {"query": "big"}},
                                {"match": {"query": "big bad"}},
                            ]
                        }
                    },
                    {"match": {"query": "wolf"}},
                ],
                "max_gaps": 0,
                "ordered": True,
            }
        }
    )
    for q in (q1, q2):
        assert q.body == body
        assert q.to_dict() == expected
        assert q.line_repr(depth=0) == (
            "intervals",
            'field=some_field, all_of={"intervals": [{"match": {"query": "the"}}, '
            '{"any_of": {"intervals": [{"match": {"query": "big"}}, {"match": {"query": '
            '"big bad"}}]}}, {"match": {"query": "wolf"}}], "max_gaps": 0, "ordered": '
            "true}",
        )


def test_match_clause():
    body = {"message": {"query": "this is a test", "operator": "and"}}
    expected = {"match": body}

    q1 = Match(field="message", query="this is a test", operator="and")
    q2 = Match(message={"query": "this is a test", "operator": "and"})
    for q in (q1, q2):
        assert q.body == body
        assert q.to_dict() == expected
        assert q.line_repr(depth=None) == (
            "match",
            'field=message, operator="and", query="this is a test"',
        )

    # short syntax
    q3 = Match(message="this is a test")
    assert q3.body == {"message": {"query": "this is a test"}}
    assert q3.to_dict() == {"match": {"message": {"query": "this is a test"}}}
    assert q3.line_repr(depth=None), ("match", 'field=message, query="this is a test"')


def test_match_bool_prefix_clause():
    body = {"message": {"query": "quick brown f", "analyzer": "keyword"}}
    expected = {"match_bool_prefix": body}

    q1 = MatchBoolPrefix(field="message", query="quick brown f", analyzer="keyword")
    q2 = MatchBoolPrefix(message={"query": "quick brown f", "analyzer": "keyword"})
    for q in (q1, q2):
        assert q.body == body
        assert q.to_dict() == expected
        assert q.line_repr(depth=None) == (
            "match_bool_prefix",
            'field=message, analyzer="keyword", query="quick brown f"',
        )

    # short syntax
    q3 = MatchBoolPrefix(message="quick brown f")
    assert q3.body == {"message": {"query": "quick brown f"}}
    assert q3.to_dict() == {
        "match_bool_prefix": {"message": {"query": "quick brown f"}}
    }
    assert q3.line_repr(depth=None) == (
        "match_bool_prefix",
        'field=message, query="quick brown f"',
    )


def test_match_phrase_clause():
    body = {"message": {"query": "this is a test", "analyzer": "my_analyzer"}}
    expected = {"match_phrase": body}

    q1 = MatchPhrase(field="message", query="this is a test", analyzer="my_analyzer")
    q2 = MatchPhrase(message={"query": "this is a test", "analyzer": "my_analyzer"})
    for q in (q1, q2):
        assert q.body == body
        assert q.to_dict() == expected
        assert q.line_repr(depth=None) == (
            "match_phrase",
            'field=message, analyzer="my_analyzer", query="this is a test"',
        )

    # short syntax
    q3 = MatchPhrase(message="this is a test")
    assert q3.body == {"message": {"query": "this is a test"}}
    assert q3.to_dict(), {"match_phrase": {"message": {"query": "this is a test"}}}
    assert q3.line_repr(depth=None) == (
        "match_phrase",
        'field=message, query="this is a test"',
    )


def test_match_phrase_prefix_clause():
    body = {"message": {"query": "this is a test", "analyzer": "my_analyzer"}}
    expected = {"match_phrase_prefix": body}

    q1 = MatchPhrasePrefix(
        field="message", query="this is a test", analyzer="my_analyzer"
    )
    q2 = MatchPhrasePrefix(
        message={"query": "this is a test", "analyzer": "my_analyzer"}
    )
    for q in (q1, q2):
        assert q.body == body
        assert q.to_dict() == expected
        assert q.line_repr(depth=None) == (
            "match_phrase_prefix",
            'field=message, analyzer="my_analyzer", query="this is a test"',
        )


def test_multi_match_clause():
    body = {
        "query": "this is a test",
        "fields": ["subject", "message"],
        "type": "best_fields",
    }
    expected = {"multi_match": body}

    q = MultiMatch(
        fields=["subject", "message"], query="this is a test", type="best_fields"
    )
    assert q.body == body
    assert q.to_dict() == expected
    assert q.line_repr(depth=None) == ("multi_match", "fields=['subject', 'message']")


def test_query_string_clause():
    body = {"query": "(new york city) OR (big apple)", "default_field": "content"}
    expected = {"query_string": body}

    q = QueryString(query="(new york city) OR (big apple)", default_field="content")
    assert q.body == body
    assert q.to_dict() == expected
    assert q.line_repr(depth=None) == (
        "query_string",
        'default_field="content", query="(new york city) OR (big apple)"',
    )


def test_simple_string_clause():
    body = {"query": "(new york city) OR (big apple)", "default_field": "content"}
    expected = {"simple_string": body}

    q = SimpleQueryString(
        query="(new york city) OR (big apple)", default_field="content"
    )
    assert q.body == body
    assert q.to_dict() == expected
    assert q.line_repr(depth=None) == (
        "simple_string",
        'default_field="content", query="(new york city) OR (big apple)"',
    )
