from typing import Any

import pytest
from hypothesis import given, strategies

from fmu.datamodels.fmu_results import global_configuration


@given(
    name=strategies.text(min_size=1),
    stratigraphic=strategies.booleans(),
    alias=strategies.one_of(
        strategies.none(),
        strategies.lists(strategies.one_of(strategies.text(), strategies.none())),
    ),
    stratigraphic_alias=strategies.one_of(
        strategies.none(),
        strategies.lists(strategies.one_of(strategies.text(), strategies.none())),
    ),
)
def test_drop_none(
    name: Any, stratigraphic: Any, alias: Any, stratigraphic_alias: Any
) -> None:
    cnf = global_configuration.StratigraphyElement(
        name=name,
        stratigraphic=stratigraphic,
        alias=alias,
        stratigraphic_alias=stratigraphic_alias,
    )
    if cnf.alias is not None:
        assert all(v is not None for v in cnf.alias)

    if cnf.stratigraphic_alias is not None:
        assert all(v is not None for v in cnf.stratigraphic_alias)


def test_access_classification_logic() -> None:
    """Test various inputs of access.ssdl and access.classification."""

    # check that ssdl.access_level is mirrored to classification
    assert (
        global_configuration.Access.model_validate(
            {
                "asset": {"name": "FakeName"},
                "ssdl": {"access_level": "internal"},
            }
        ).classification
        == "internal"
    )
    assert (
        global_configuration.Access.model_validate(
            {
                "asset": {"name": "FakeName"},
                "ssdl": {"access_level": "restricted"},
            }
        ).classification
        == "restricted"
    )
    # classification together with ssdl.access_level should warn
    # and ignore the ssdl_access level
    with pytest.warns(match="The config contains both"):
        assert (
            global_configuration.Access.model_validate(
                {
                    "asset": {"name": "FakeName"},
                    "ssdl": {"access_level": "internal"},
                    "classification": "restricted",
                }
            ).classification
            == "restricted"
        )
    # classification together with ssdl.rep_include is ok
    global_configuration.Access.model_validate(
        {
            "asset": {"name": "FakeName"},
            "ssdl": {"rep_include": True},
            "classification": "internal",
        }
    )
    # ssdl is optional as long as classification is present
    global_configuration.Access.model_validate(
        {
            "asset": {"name": "FakeName"},
            "classification": "internal",
        }
    )
    # missing classification and ssdl.access_level should fail
    with pytest.raises(ValueError, match="Please provide access.classification"):
        global_configuration.Access.model_validate(
            {
                "asset": {"name": "FakeName"},
                "ssdl": {"rep_include": False},
            }
        )


# --------------------------------------------------------------------------------------
# Stratigraphy
# --------------------------------------------------------------------------------------


def test_stratigraphy_dunder_iter(
    testdata_stratigraphy: global_configuration.Stratigraphy,
) -> None:
    try:
        count = 0
        for _ in testdata_stratigraphy:
            count += 1
        assert count == len(testdata_stratigraphy.root)
    except Exception:
        pytest.fail("Stratigraphy class does not have __iter__()")


def test_stratigraphy_dunder_getitem(
    testdata_stratigraphy: global_configuration.Stratigraphy,
) -> None:
    try:
        testdata_stratigraphy["TopStratUnit2"]
    except Exception:
        pytest.fail("Stratigraphy class does not have __getitem__()")
