import pytest

from clarabot_nano.server.general.solr.input_processing import UniversalQueryInputProcessor
from clarabot_nano.server.general.solr.reflect import SolrSchemaQueryReflector, InvalidQueryError

_SCHEMA_HU_EN = {
    "fields": [
        {"name": "summary_faba"},
        {"name": "text_faba", "storeOffsetsWithPositions": True, "stored": True},
        {"name": "summary_hu"},
        {"name": "text_hu", "storeOffsetsWithPositions": True, "stored": True},
        {"name": "summary_hu_ex"},
        {"name": "text_hu_ex"},
        {"name": "summary_en"},
        {"name": "text_en", "storeOffsetsWithPositions": True, "stored": True},
        {"name": "summary_en_ex"},
        {"name": "text_en_ex"},
    ]
}


def test_server_solr_input_processing():
    p = UniversalQueryInputProcessor()
    assert p.process("") == ""
    for c in "*?{}[]:\\":
        assert p.process(c) == "\\" + c
    assert p.process("*") == "\\*"
    assert p.process("\\*") == "\\\\\\*"
    assert p.process("\\\\*") == "\\\\\\\\\\*"
    assert p.process("\\*\\") == "\\\\\\*\\\\"


def test_server_solr_reflector_query():
    r = SolrSchemaQueryReflector()
    r.reflect_solr_schema(
        {
            "fields": [
                {"name": "summary_faba"},
                {"name": "text_faba", "storeOffsetsWithPositions": True, "stored": True},
                {"name": "summary_hu"},
                {"name": "text_hu", "storeOffsetsWithPositions": True, "stored": True},
                {"name": "summary_hu_ex"},
                {"name": "text_hu_ex"},
            ]
        }
    )
    assert r.reflected is True
    assert r.languages == ["hu"]
    assert r.highlight_field_by_language == {"faba": "text_faba", "hu": "text_hu"}
    assert r.query_fields_by_language == {
        "hu": "summary_hu_ex^4.78 text_hu_ex^3.68 summary_hu^2.73 text_hu^2.1 summary_faba^0.91 text_faba^0.7",
        "": "summary_hu_ex^2.27 text_hu_ex^1.75 summary_hu^1.3 text_hu summary_faba^0.91 text_faba^0.7",
        None: "summary_hu_ex^2.27 text_hu_ex^1.75 summary_hu^1.3 text_hu summary_faba^0.91 text_faba^0.7",
    }, str(r.query_fields_by_language)
    assert r.highlight_fields == "text_faba text_hu"
    assert (
        r.create_search_query_fields(r.FALLBACK_FIELD, r.languages)
        == "summary_hu_ex^2.27 text_hu_ex^1.75 summary_hu^1.3 text_hu summary_faba^2.73 text_faba^2.1"
    )

    r = SolrSchemaQueryReflector()
    r.reflect_solr_schema(_SCHEMA_HU_EN)
    assert r.reflected is True
    assert r.languages == ["en", "hu"]
    assert r.highlight_field_by_language == {"faba": "text_faba", "en": "text_en", "hu": "text_hu"}
    assert r.query_fields_by_language == {
        "en": "summary_en_ex^4.78 text_en_ex^3.68 summary_en^2.73 text_en^2.1 summary_hu_ex^2.27 text_hu_ex^1.75 "
        "summary_hu^1.3 text_hu summary_faba^0.91 text_faba^0.7",
        "hu": "summary_en_ex^2.27 text_en_ex^1.75 summary_en^1.3 text_en summary_hu_ex^4.78 text_hu_ex^3.68 "
        "summary_hu^2.73 text_hu^2.1 summary_faba^0.91 text_faba^0.7",
        "": "summary_en_ex^2.27 text_en_ex^1.75 summary_en^1.3 text_en summary_hu_ex^2.27 text_hu_ex^1.75 "
        "summary_hu^1.3 text_hu summary_faba^0.91 text_faba^0.7",
        None: "summary_en_ex^2.27 text_en_ex^1.75 summary_en^1.3 text_en summary_hu_ex^2.27 text_hu_ex^1.75 "
        "summary_hu^1.3 text_hu summary_faba^0.91 text_faba^0.7",
    }, str(r.query_fields_by_language)
    assert r.highlight_fields == "text_en text_faba text_hu"


def test_server_solr_reflector_build_query():
    r = SolrSchemaQueryReflector()
    r.reflect_solr_schema(_SCHEMA_HU_EN)

    with pytest.raises(InvalidQueryError, match="Accessor root must not be empty"):
        r.create_search_query_args("", "large")

    assert (x := r.create_search_query_args("/tmp/xy", "large VAGY big", "BOB")) == [
        ("defType", "edismax"),
        (
            "qf",
            "summary_en_ex^2.27 text_en_ex^1.75 summary_en^1.3 text_en "
            "summary_hu_ex^2.27 text_hu_ex^1.75 summary_hu^1.3 text_hu "
            "summary_faba^0.91 text_faba^0.7",
        ),
        ("q", "large VAGY big"),
        ("rows", 20),
        ("fl", "path,accessors,size,mtime,score,img_data,img_bucket"),
        ("sort", "score desc"),
        ("fq", "file:1"),
        ("fq", 'accessors:"/tmp/xy"'),
        ("mm.autoRelax", "true"),
        ("hl", "true"),
        ("hl.fl", "text_en text_faba text_hu"),
        ("tie", "0.11"),
    ], f"{x}"

    assert (x := r.create_search_query_args('C:\\tmp\\"xy', "\\*?{}[]:yes")) == [
        ("defType", "edismax"),
        (
            "qf",
            "summary_en_ex^2.27 text_en_ex^1.75 summary_en^1.3 text_en "
            "summary_hu_ex^2.27 text_hu_ex^1.75 summary_hu^1.3 text_hu "
            "summary_faba^0.91 text_faba^0.7",
        ),
        ("q", "\\\\\\*\\?\\{\\}\\[\\]\\:yes"),
        ("rows", 20),
        ("fl", "path,accessors,size,mtime,score,img_data,img_bucket"),
        ("sort", "score desc"),
        ("fq", "file:1"),
        ("fq", 'accessors:"C:\\\\tmp\\\\\\"xy"'),
        ("mm.autoRelax", "true"),
        ("hl", "true"),
        ("hl.fl", "text_en text_faba text_hu"),
        ("tie", "0.11"),
    ], f"{x}"

    assert (x := r.create_search_query_args("/tmp/x stor of y/yes", "large VAGY big", "hu")) == [
        ("defType", "edismax"),
        (
            "qf",
            "summary_en_ex^2.27 text_en_ex^1.75 summary_en^1.3 text_en "
            "summary_hu_ex^4.78 text_hu_ex^3.68 summary_hu^2.73 text_hu^2.1 "
            "summary_faba^0.91 text_faba^0.7",
        ),
        ("q", "large OR big"),
        ("rows", 20),
        ("fl", "path,accessors,size,mtime,score,img_data,img_bucket"),
        ("sort", "score desc"),
        ("fq", "file:1"),
        ("fq", 'accessors:"/tmp/x stor of y/yes"'),
        ("mm.autoRelax", "true"),
        ("hl", "true"),
        ("hl.fl", "text_en text_faba text_hu"),
        ("tie", "0.11"),
    ], f"{x}"
