from demoproject.demoapp.models import Strategy1
from strategy_field.fields import (
    MultipleStrategyClassFieldDescriptor,
    MultipleStrategyFieldDescriptor,
    StrategyClassFieldDescriptor,
    StrategyFieldDescriptor,
)
from strategy_field.utils import fqn


class MockField:
    value = fqn(StrategyFieldDescriptor)
    import_error = None
    factory = lambda x, s: x(s)

    # name = 'strategy'
    def __init__(self, owner=None):
        pass


class MockModel:
    def __init__(self):
        self.strategy = fqn(MockField)
        self.errored = "3333"


class MultipleMockModel:
    def __init__(self):
        self.strategy = [fqn(MockField)]
        self.strategy1 = "test_descriptors.MockField,"
        self.strategy2 = MockField
        self.errored = ["3333"]


def test_strategyclassfielddescriptor():
    desc1 = StrategyClassFieldDescriptor(
        type("Field", (MockField,), {"name": "strategy"})
    )
    desc3 = StrategyClassFieldDescriptor(
        type(
            "Field",
            (MockField,),
            {"name": "errored", "import_error": lambda *a: Strategy1},
        )
    )

    # strategy
    obj = MockModel()
    assert desc1.__get__(None) is None
    assert desc1.__get__(obj) == "test_descriptors.MockField"

    assert desc3.__set__(obj, 22) is None

    desc1.__set__(obj, fqn(StrategyClassFieldDescriptor))
    assert obj.strategy == StrategyClassFieldDescriptor


def test_multiplestrategyclassfielddescriptor():
    desc0 = MultipleStrategyClassFieldDescriptor(
        type("Field", (MockField,), {"name": "strategy"})
    )
    desc1 = MultipleStrategyClassFieldDescriptor(
        type("Field", (MockField,), {"name": "strategy1"})
    )
    desc2 = MultipleStrategyClassFieldDescriptor(
        type("Field", (MockField,), {"name": "strategy2"})
    )
    desc3 = MultipleStrategyClassFieldDescriptor(
        type("Field", (MockField,), {"name": "errored"})
    )
    desc4 = MultipleStrategyClassFieldDescriptor(
        type("Field", (MockField,), {"name": "errored", "import_error": lambda *a: 22})
    )

    # strategy
    obj = MultipleMockModel()
    assert desc0.__get__(None) is None
    assert desc0.__get__(obj) == [MockField]

    assert desc1.__get__(obj) == [MockField]
    assert desc2.__get__(obj) == [MockField]

    assert desc3.__get__(obj) is None
    assert desc4.__get__(obj) == 22

    #
    desc1.__set__(obj, [fqn(StrategyClassFieldDescriptor)])
    assert obj.strategy1 == ["strategy_field.fields.StrategyClassFieldDescriptor"]


def test_strategyfielddescriptor():
    desc1 = StrategyFieldDescriptor(type("Field", (MockField,), {"name": "strategy"}))
    # desc2 = StrategyFieldDescriptor(type("Field", (MockField,), {'name': 'errored'}))
    desc3 = StrategyFieldDescriptor(
        type(
            "Field", (MockField,), {"name": "errored", "import_error": lambda *a: None}
        )
    )

    # strategy
    obj = MockModel()
    assert desc1.__get__(None) is None
    assert desc1.__get__(obj) == "test_descriptors.MockField"

    # assert desc2.__get__(obj) == '3333'
    # assert desc3.__get__(obj) == '3333'

    desc1.__set__(obj, fqn(StrategyClassFieldDescriptor))
    assert isinstance(obj.strategy, StrategyClassFieldDescriptor)

    desc1.__set__(obj, 0)
    assert obj.strategy is None

    desc1.__set__(obj, "--")
    assert obj.strategy is None

    desc3.__set__(obj, "--")
    assert obj.strategy is None


def test_MultipleStrategyFieldDescriptor():
    desc0 = MultipleStrategyFieldDescriptor(
        type("Field", (MockField,), {"name": "strategy"})
    )
    desc1 = MultipleStrategyFieldDescriptor(
        type("Field", (MockField,), {"name": "strategy1"})
    )
    # desc2 = MultipleStrategyFieldDescriptor(type("Field", (MockField,), {'name': 'strategy2'}))
    desc3 = MultipleStrategyFieldDescriptor(
        type("Field", (MockField,), {"name": "errored"})
    )
    desc4 = MultipleStrategyFieldDescriptor(
        type("Field", (MockField,), {"name": "errored", "import_error": lambda *a: 22})
    )

    # strategy
    obj = MultipleMockModel()
    assert desc0.__get__(None) == []
    # assert desc0.__get__(obj) == [MockField]

    # assert desc1.__get__(obj) == [MockField]
    # assert desc2.__get__(obj) == [MockField]

    assert desc3.__get__(obj) == []
    assert desc4.__get__(obj) == []

    #
    desc1.__set__(obj, [fqn(StrategyClassFieldDescriptor)])
    assert obj.strategy1 == ["strategy_field.fields.StrategyClassFieldDescriptor"]
