import pytest

from benchlingapi.models import ModelRegistry
from benchlingapi.models.mixins import ArchiveMixin
from benchlingapi.models.mixins import CreateMixin
from benchlingapi.models.mixins import EntityMixin
from benchlingapi.models.mixins import GetMixin
from benchlingapi.models.mixins import InventoryMixin
from benchlingapi.models.mixins import ListMixin
from benchlingapi.models.mixins import RegistryMixin
from benchlingapi.models.models import Folder
from benchlingapi.models.models import Project


def pytest_generate_tests(metafunc):
    # parameterize with models that match the expected model test
    only_models = ModelRegistry.filter_models_by_base_classes(metafunc.cls.only)

    create_params_dict = metafunc.cls.__dict__.get("create_params", {})

    argdict = {"model": [], "create_params": []}
    for m in only_models:
        create_params = create_params_dict.get(m.__name__, None)
        if isinstance(create_params, list):
            for cp in create_params:
                argdict["model"].append(m)
                argdict["create_params"].append(cp)
        else:
            argdict["model"].append(m)
            argdict["create_params"].append(create_params)

    argnames = [n for n in metafunc.fixturenames if n in argdict]
    argvalues = zip(*[argdict[n] for n in argnames])

    if len(argnames) == 1:
        argvalues = [a[0] for a in argvalues]

    metafunc.parametrize(",".join(argnames), argvalues, scope="class")


class HasInterface:
    @pytest.fixture(scope="function")
    def interface(self, session, model):
        return session.interface(model.__name__)


class HasExample(HasInterface):
    @pytest.fixture(scope="function")
    def example_model(self, interface, model):
        one = interface.one()
        if not one:
            pytest.skip('Example model "{}" not found'.format(model.__name__))
        return one


class TestListMixin(HasExample):
    only = ListMixin

    def test_one(self, example_model):
        assert example_model

    def test_last_1(self, interface, model):
        size1 = interface.last(1)
        if len(size1) == 0:
            pytest.skip('No models found for "{}"'.format(model))
        assert 1 == len(size1)
        assert isinstance(size1[0], model)

    def test_last_20(self, interface, model):
        size20 = interface.last(20)
        if len(size20) == 0:
            pytest.skip('No models found for "{}"'.format(model))
        size_list = interface.list()
        assert min(len(size20), len(size_list)) <= 20
        assert isinstance(size20[-1], model)

    def test_find_by_name(self, interface, model, example_model):
        found = interface.find_by_name(example_model.name)
        assert found.name == example_model.name
        assert isinstance(found, model)

    def test_list_pages(self, interface, model):
        list(interface.list_pages(page_limit=1, page_size=1))


class TestGetMixin(HasExample):
    only = [ListMixin, GetMixin]

    def test_find(self, interface, example_model):
        assert interface.get(example_model.id) is not None
        assert interface.find(example_model.id) is not None
        assert interface.find("asdf98qw4hotnof8gyh") is None


class TestEntity(HasInterface):