# coding: utf-8

import logging

from django.conf import settings
from django.db import transaction, IntegrityError

from django_yauth.authentication_mechanisms.cookie import Mechanism as CookieMechanism
from django_yauth.authentication_mechanisms.oauth import Mechanism as OauthMechanism
from django_yauth.authentication_mechanisms.base import BaseMechanism
from django_yauth.authentication_mechanisms.tvm.request import TvmServiceRequest, TvmImpersonatedRequest

from events.accounts.models import User


logger = logging.getLogger(__name__)


class FormsAnonymousUserMixin(object):
    def get_user(self, create_on_missing=True):
        try:
            return User.objects.get(pk=settings.MOCK_PROFILE_ID)
        except User.DoesNotExist:
            # такое может быть только в тестах
            return None

    @property
    def is_anonymous(self):
        return True


class FormsYandexUserMixin(object):
    def get_user(self, create_on_missing=True):
        user_obj = getattr(self, '_user_obj', None)
        if user_obj is None:
            user_obj = self._get_or_create_user()
            setattr(self, '_user_obj', user_obj)
        return user_obj

    def _get_or_create_user(self):
        cloud_uid = getattr(self, 'cloud_uid', None)
        orgs = getattr(self, 'orgs', None)
        with transaction.atomic():
            try:
                dir_id = orgs[0] if orgs else None
                user = User.objects.get_or_create_user(self.uid, cloud_uid, dir_id)
            except IntegrityError as e:
                logger.warn('IntegrityError: %s', e)
                user = None
        if not user:
            user = (
                User.objects.using(settings.DATABASE_DEFAULT)
                .filter_uid_or_cloud_uid(self.uid, cloud_uid)
                .first()
            )
        return user

    @property
    def is_anonymous(self):
        return False

    def has_perm(self, *args, **kwargs):
        # todo: test me
        return self.get_user().has_perm(*args, **kwargs)

    def has_perms(self, *args, **kwargs):
        # todo: test me
        return self.get_user().has_perms(*args, **kwargs)


class CookieAuthenticator(object):
    source = 'session_id'


class OAuthAuthenticator(object):
    source = 'oauth'


class FormsCookieYandexUser(FormsYandexUserMixin, CookieMechanism.YandexUser):
    authenticator = CookieAuthenticator()


class FormsOauthYandexUser(FormsYandexUserMixin, OauthMechanism.YandexUser):
    authenticator = OAuthAuthenticator()


class FormsAnonymousYandexUser(FormsAnonymousUserMixin, BaseMechanism.AnonymousYandexUser):
    pass


class FormsTestYandexUser(FormsCookieYandexUser):
    pass


class FormsTVM2YandexUser(FormsYandexUserMixin, TvmImpersonatedRequest):
    pass


class FormsTVM2YandexServiceUser(FormsYandexUserMixin, TvmServiceRequest):
    pass
