import json

from osw.utils.oold import (
    AggregateGeneratedSchemasParam,
    AggregateGeneratedSchemasParamMode,
    aggregate_generated_schemas,
    deep_equal,
    escape_json_strings,
    merge_deep,
    merge_jsonld_context_object_list,
    unique_array,
)


def test_deep_equal():
    assert deep_equal({"a": 1, "b": 2}, {"a": 1, "b": 2}) is True
    assert deep_equal({"a": 1, "b": 2}, {"a": 1, "b": 3}) is False
    assert deep_equal({"a": 1, "b": 2}, {"a": 1}) is False
    assert deep_equal({"a": 1, "b": 2}, {"a": 1, "b": 2, "c": 3}) is False
    assert deep_equal({"a": 1, "b": 2}, {"b": 2, "a": 1}) is True

    assert deep_equal([1, 2, 3], [1, 2, 3]) is True
    assert deep_equal([1, 2, 3], [1, 2, 4]) is False
    assert deep_equal([1, 2, 3], [1, 2]) is False
    assert deep_equal([1, 2, 3], [1, 2, 3, 4]) is False

    assert deep_equal({"a": 1, "b": [1, 2, 3]}, {"a": 1, "b": [1, 2, 3]}) is True
    assert deep_equal({"a": 1, "b": [1, 2, 3]}, {"a": 1, "b": [1, 2, 4]}) is False


def test_unique_array():
    assert unique_array([1, 2, 3, 1, 2, 3]) == [1, 2, 3]
    assert unique_array([1, 2, 3]) == [1, 2, 3]
    assert unique_array([1, 2, 3, 4, 5]) == [1, 2, 3, 4, 5]
    assert unique_array([1, 2, 3, 4, 5, 1, 2, 3]) == [1, 2, 3, 4, 5]


def test_deep_merge():
    assert merge_deep({"a": 1, "b": 2}, {"a": 1, "b": 2}) == {"a": 1, "b": 2}
    assert merge_deep({"a": 1, "b": 2}, {"a": 1, "b": 3}) == {"a": 1, "b": 3}
    assert merge_deep({"a": 1, "b": 2}, {"a": 1}) == {"a": 1, "b": 2}
    assert merge_deep({"a": 1, "b": 2}, {"a": 1, "b": 2, "c": 3}) == {
        "a": 1,
        "b": 2,
        "c": 3,
    }
    assert merge_deep({"a": 1, "b": 2}, {"b": 2, "a": 1}) == {"a": 1, "b": 2}

    assert merge_deep([1, 2, 3], [1, 2, 3]) == [1, 2, 3]
    assert merge_deep([1, 2, 3], [1, 2, 4]) == [1, 2, 3, 4]
    assert merge_deep([1, 2, 3], [1, 2]) == [1, 2, 3]
    assert merge_deep([1, 2, 3], [1, 2, 3, 4]) == [1, 2, 3, 4]
    assert merge_deep([1, 2, {"a": 2}, 3], [1, {"a": 2}, 4]) == [1, 2, {"a": 2}, 3, 4]

    assert merge_deep({"a": 1, "b": [1, 2, 3]}, {"a": 1, "b": [1, 2, 3]}) == {
        "a": 1,
        "b": [1, 2, 3],
    }
    assert merge_deep({"a": 1, "b": [1, 2, 3]}, {"a": 1, "b": [1, 2, 4]}) == {
        "a": 1,
        "b": [1, 2, 3, 4],
    }


def test_merge_jsonld_context_object_list():
    assert merge_jsonld_context_object_list(["a", "b", "c"]) == ["a", "b", "c"]
    assert merge_jsonld_context_object_list(["a", {"b": 1}, "c"]) == [
        "a",
        {"b": 1},
        "c",
    ]
    assert merge_jsonld_context_object_list(["a", {"b": 1}, {"c": 2}]) == [
        "a",
        {"b": 1, "c": 2},
    ]
    assert merge_jsonld_context_object_list(["a", {"b": 1}, {"b": 2}]) == [
        "a",
        {"b": 2},
    ]
    assert merge_jsonld_context_object_list(["a", {"b": 1}, "c", {"b": 2}]) == [
        "a",
        {"b": 1},
        "c",
        {"b": 2},
    ]


def test_aggregate_generated_schemas():
    param = AggregateGeneratedSchemasParam(
        target_schema={"a": 1, "b": 2},
        generated_schemas={"schema1": {"b": 3, "c": 4}, "schema2": {"b": 5, "d": 6}},
        mode=AggregateGeneratedSchemasParamMode.ROOT_LEVEL,
    )
    result = aggregate_generated_schemas(param)
    assert result.aggregated_schema == {"a": 1, "b": 5, "c": 4, "d": 6}

    param = AggregateGeneratedSchemasParam(
        target_schema={"a": 1, "b": 2},
        generated_schemas={"schema1": {"b": 3, "c": 4}, "schema2": {"b": 5, "d": 6}},
        mode=AggregateGeneratedSchemasParamMode.DEFINITIONS_SECTION,
    )
    result = aggregate_generated_schemas(param)
    assert result.aggregated_schema == {
        "a": 1,
        "b": 2,
        "$defs": {
            "generated": {
                "$comment": "Autogenerated section - do not edit. "
                "Generated from schema1 schema2",
                "b": 5,
                "c": 4,
                "d": 6,
            }
        },
        "allOf": [{"$ref": "#/$defs/generated"}],
    }

    param = AggregateGeneratedSchemasParam(
        target_schema={"a": 1, "b": 2},
        generated_schemas={"schema1": {"b": 3, "c": 4}, "schema2": {"b": 5, "d": 6}},
        mode=AggregateGeneratedSchemasParamMode.DEFINITIONS_SECTION,
        generate_root_ref=True,
    )
    result = aggregate_generated_schemas(param)
    assert result.aggregated_schema == {
        "a": 1,
        "b": 2,
        "$defs": {
            "generated": {
                "$comment": "Autogenerated section - do not edit. "
                "Generated from schema1 schema2",
                "b": 5,
                "c": 4,
                "d": 6,
            }
        },
        "$ref": "#/$defs/generated",
    }


def test_escape_json_strings():
    org_data = {
        "test": "normal string",
        "test2": 'string with "double quotes"',
        "test3": r"latex command $\textit{impedance}$",
        "test4": r"math $$M \cdot L^2 \cdot  T^{-2} \cdot N^{-1}$$",
    }
    data = escape_json_strings(org_data)

    data_string = "{"
    # serialize manually to json as a handlebars template would do
    for key, value in data.items():
        data_string += f'\n   "{key}": "{value}"'
        if key != list(data.keys())[-1]:
            data_string += ", "
    data_string += "\n}"
    data = data_string

    result = json.loads(data)

    assert result == org_data
