"""Defines some model to test the versionable app."""

from django.conf import settings
from django.db import models

from ...models import Dependency, Versionable


# Do we have to test django-polymorphic specificities
try:
    # This import is just to set ``TEST_POLYMORPHIC``
    # pylint: disable=unused-import,wrong-import-order
    from polymorphic.models import PolymorphicModel
except ImportError:
    TEST_POLYMORPHIC = False
else:
    TEST_POLYMORPHIC = True


class StrHelper(models.Model):
    """Helper that defines a debug-readable representation of a model instance."""

    class Meta:
        abstract = True

    def __str__(self):
        """Display the Pk and, if available, the name."""

        if 'name' in self._meta.get_fields():
            return '#%s (%s)' % (self.pk, self.name)
        else:
            return '#%s' % self.pk


class VersionableModel1(StrHelper, Versionable):
    """Root of our ``versionable`` tree."""

    name = models.CharField(max_length=100)
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    lang = models.CharField(max_length=2, default='fr')


class DependencyModel1(StrHelper, Dependency):
    """A model depending on the ``VersionableModel`` one."""

    versionable_link = (VersionableModel1, 'parent')

    parent = models.ForeignKey(to=VersionableModel1, on_delete=models.CASCADE)
    name = models.CharField(max_length=100)


class DependencyModel2(StrHelper, Dependency):
    """A model depending on the ``VersionableModel`` one."""

    versionable_link = (VersionableModel1, 'parent')

    parent = models.ForeignKey(to=VersionableModel1, on_delete=models.CASCADE)
    name = models.CharField(max_length=100)


class DependencyModelParentNull(StrHelper, Dependency):
    """A model depending on the ``VersionableModel`` one."""

    versionable_link = (VersionableModel1, 'parent')

    parent = models.ForeignKey(
        to=VersionableModel1,
        blank=True,
        null=True,
        on_delete=models.CASCADE
    )
    name = models.CharField(max_length=100)


class SubDependencyModel1(StrHelper, Dependency):
    """A model depending on the ``VersionableModel`` one via ``DependencyModel1``."""

    versionable_link = (VersionableModel1, 'parent__parent')

    parent = models.ForeignKey(to=DependencyModel1, on_delete=models.CASCADE)
    name = models.CharField(max_length=100)
    items = models.ManyToManyField('NonDependencyModel', related_name='links')


class SubDependencyModelParentNull(StrHelper, Dependency):
    """A model depending on the ``VersionableModel`` one via ``DependencyModelParentNull``."""

    versionable_link = (VersionableModel1, 'parent__parent')

    parent = models.ForeignKey(to=DependencyModelParentNull, on_delete=models.CASCADE)
    name = models.CharField(max_length=100)

class NonDependencyModel(StrHelper, models.Model):
    """A model not in the dependency tree, but used as M2M in SubDependencyModel1."""

    name = models.CharField(max_length=100)


if TEST_POLYMORPHIC:
    # Some models to test the specific model and manager for polymorphic duplicable models

    # pylint: disable=wrong-import-position
    from ...managers import (
        PolymorphicManagerForDependency,
        PolymorphicManagerForVersionable,
        PolymorphicQuerySetForDependency,
        PolymorphicQuerySetForVersionable,
    )
    from ...models import PolymorphicModelForDependency, PolymorphicModelForVersionable

    class PolymorphicBase(StrHelper, Versionable, PolymorphicModelForVersionable):
        """Base model to test ``PolymorphicModelForVersionable``"""

        name = models.CharField(max_length=100)
        objects = PolymorphicManagerForVersionable()

    class PolymorphicChild1(PolymorphicBase):
        """First child model to test ``PolymorphicModelForVersionable``"""

        name1 = models.CharField(max_length=100)

    class TestPolymorphicQuerySet(PolymorphicQuerySetForVersionable):
        """To test the override of the ``PolymorphicQuerySetForVersionable``"""

        def name_is_foo(self):
            """Return entries with name being "foo"."""
            return self.filter(name='foo')

    class TestPolymorphicManager(
            PolymorphicManagerForVersionable.from_queryset(TestPolymorphicQuerySet)
        ):
        """To test the override of the ``PolymorphicManagerForVersionable``"""

        def do_nothing(self):
            """Simple method to test if we can access it"""
            pass

    class PolymorphicChild2(PolymorphicBase):
        """Second child model to test ``PolymorphicModelForVersionable``"""

        name2 = models.CharField(max_length=100)

        versionable_objects = TestPolymorphicManager()

    class PolymorphicDependencyBase(StrHelper, Dependency, PolymorphicModelForDependency):
        """Base model to test ``PolymorphicModelForVersionable``"""

        versionable_link = (PolymorphicChild1, 'parent')

        parent = models.ForeignKey(
            PolymorphicChild1,
            related_name='children',
            on_delete=models.CASCADE
        )
        name = models.CharField(max_length=100)

        objects = PolymorphicManagerForDependency()


    class TestPolymorphicDependencyQuerySet(PolymorphicQuerySetForDependency):
        """To test the override of the ``PolymorphicQuerySetForDependency``"""

        def name_is_foo(self):
            """Return entries with name being "foo"."""
            return self.filter(name='foo')

    class TestPolymorphicDependencyManager(
            PolymorphicManagerForDependency.from_queryset(TestPolymorphicQuerySet)
        ):
        """To test the override of the ``PolymorphicManagerForDependency``"""

        def do_nothing(self):
            """Simple method to test if we can access it"""
            pass

    class PolymorphicDependencyChild1(PolymorphicDependencyBase):
        """First child model to test ``PolymorphicModelForVersionable``"""

        name1 = models.CharField(max_length=100)
        items = models.ManyToManyField('SubDependencyModel2', related_name='links')

        objects = TestPolymorphicDependencyManager()

    class PolymorphicDependencyChild2(PolymorphicDependencyBase):
        """Second child model to test ``PolymorphicModelForVersionable``"""

        name2 = models.CharField(max_length=100)

    class SubDependencyModel2(StrHelper, models.Model):
        """Model to test M2M edition when the versionable is a polymorphic model"""

        name = models.CharField(max_length=100)
