# -*- coding: utf-8 -*-

import os
import uuid

from django.conf import settings
from django.core.files import File
from django.utils import timezone

import factory

from .constants import (
    GROUPTYPE_INTERNAL, GROUPTYPE_BUSINESS_UNIT,
    GROUPTYPE_JOB_PROFILE, INTERNAL_GROUP_TRAINEE,
    INTERNAL_GROUP_TRAINER,
)
from .models import Avatar, Group, GroupRole, GroupSet, GroupType, MTPUser


class AvatarFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Avatar

    img = factory.LazyAttribute(lambda o: File(open(
        os.path.join(settings.PROJECT_ROOT, 'assets', 'magency.png')
    )))
    hash = factory.Sequence(lambda n: str(uuid.uuid4()))


class GroupSetFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = GroupSet


class GroupTypeFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = GroupType
        django_get_or_create = ('name',)

    name = factory.Sequence(lambda n: 'GroupType-%d' % n)


class GroupFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Group

    name = factory.Sequence(lambda n: 'Group-%d' % n)
    type = factory.SubFactory(GroupTypeFactory)


class GroupRoleFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = GroupRole


class JobProfileFactory(GroupFactory):
    name = factory.Sequence(lambda n: 'JobProfile-%d' % n)
    type = factory.SubFactory(GroupTypeFactory, name=GROUPTYPE_JOB_PROFILE)


class BusinessUnitFactory(GroupFactory):
    name = factory.Sequence(lambda n: 'BusinessUnit-%d' % n)
    type = factory.SubFactory(GroupTypeFactory, name=GROUPTYPE_BUSINESS_UNIT)


class MTPUserFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = MTPUser

    username = factory.Sequence(lambda n: 'mtptest-%02d' % n)
    first_name = factory.Sequence(lambda n: 'Firstname-%02d' % n)
    last_name = factory.Sequence(lambda n: 'Lastname-%02d' % n)
    email = factory.LazyAttribute(lambda o: '%s@magency.fr' % o.username)

    # FIXME: Reactivate once the unicode error resolved.
    # FIXME: WTF is "the unicode error"?
    # photo = factory.SubFactory(AvatarFactory)

    last_changed_password = factory.LazyAttribute(lambda o: timezone.now())

    @classmethod
    def _create(cls, model_class, *args, **kwargs):
        """Override the default ``_create`` with our custom call to set the password correctly.

        Notes
        -----
        http://factoryboy.readthedocs.org/en/latest/recipes.html#custom-manager-methods
        """
        manager = cls._get_manager(model_class)
        # The default would use ``manager.create(*args, **kwargs)``.
        # And we can't use the ``create_user`` method from the user manager because ``is_staff`` and
        # ``is_superuser`` are forced to ``False``.
        user_kwargs = kwargs.copy()

        is_active = user_kwargs.pop('is_active', True)  # Force to ``True``

        user = manager._create_user(
            user_kwargs.pop('username'),
            user_kwargs.pop('email'),
            user_kwargs.pop('password', None),
            user_kwargs.pop('is_staff', False),
            user_kwargs.pop('is_superuser', False),
            **user_kwargs
        )
        if not is_active:
            user.is_active = False
            user.save()

        return user


class TraineeFactory(MTPUserFactory):
    username = factory.Sequence(lambda n: 'trainee-%02d' % n)
    first_name = factory.Sequence(lambda n: 'Trai-%02d' % n)
    last_name = factory.Sequence(lambda n: 'Nee-%02d' % n)

    @factory.post_generation
    def groups(self, create, extracted, **kwargs):
        internal_group_type, _ = GroupType.objects.get_or_create(
            name=GROUPTYPE_INTERNAL
        )

        group, __ = Group.objects.get_or_create(
            type=internal_group_type,
            name=INTERNAL_GROUP_TRAINEE,
        )

        GroupRole.objects.create(
            user=self,
            group=group,
        )


class TrainerFactory(MTPUserFactory):
    username = factory.Sequence(lambda n: 'trainer-%02d' % n)
    first_name = factory.Sequence(lambda n: 'Trai-%02d' % n)
    last_name = factory.Sequence(lambda n: 'Ner-%02d' % n)

    is_staff = True

    @factory.post_generation
    def groups(self, create, extracted, **kwargs):
        internal_group_type, _ = GroupType.objects.get_or_create(
            name=GROUPTYPE_INTERNAL
        )

        group, __ = Group.objects.get_or_create(
            type=internal_group_type,
            name=INTERNAL_GROUP_TRAINER,
        )

        GroupRole.objects.create(
            user=self,
            group=group,
        )


class StaffFactory(TrainerFactory):
    username = factory.Sequence(lambda n: 'staff-%02d' % n)
    first_name = factory.Sequence(lambda n: 'St-%02d' % n)
    last_name = factory.Sequence(lambda n: 'Aff-%02d' % n)

    is_superuser = False
    is_staff = True


class AdminFactory(TrainerFactory):
    username = factory.Sequence(lambda n: 'admin-%02d' % n)
    first_name = factory.Sequence(lambda n: 'Ad-%02d' % n)
    last_name = factory.Sequence(lambda n: 'Min-%02d' % n)

    is_superuser = True
    is_staff = True
