# -*- coding: utf-8 -*-
"""tests.py: Tests for messages-extends"""

import datetime
from unittest import mock

from django.conf import settings
from django.contrib import messages
from django.contrib.auth import authenticate
from django.contrib.auth.models import AnonymousUser, User
from django.contrib.messages.storage import default_storage
from django.db.models.deletion import Collector
from django.test.client import RequestFactory

from messages_extends.storages import PersistentStorage

from django.urls import reverse
from django.test import Client, TestCase
from django.test.utils import override_settings

from messages_extends.constants import PERSISTENT_MESSAGE_LEVELS, WARNING_PERSISTENT
from messages_extends.models import Message

class MessagesClient(Client):
    """ Baseline Client for Messages Extends.  This is needed to hook messages into the client
    and assign the user attribute to the request object"""

    def __init__(self, **defaults):
        """Adds messages to the request"""
        super(MessagesClient, self).__init__(**defaults)
        if 'django.contrib.messages' in settings.INSTALLED_APPS:
            self._messages = default_storage(self)

    def login(self, **credentials):
        """This sets the user attibute for a logged in user"""
        if super(MessagesClient, self).login(**credentials):
            self.user = authenticate(**credentials)
            return True
        else:
            self.user = AnonymousUser()
        return False

    def logout(self):
        logout = super(MessagesClient, self).logout()
        if hasattr(self, 'user'):
            self.user = None
        return logout


class MessagesTests(TestCase):
    """Test out homes app"""
    client_class = MessagesClient

    def _get_user(self, username="bob"):
        """Give up a user"""
        user = User.objects.create(username=username)
        user.set_password('password')
        user.save()
        return user

    @override_settings(MESSAGE_LEVEL=1)
    def test_persist_message_levels(self):
        """Test the basic messaging"""
        user =self._get_user()
        self.client.login(username=user.username, password='password')
        for level in PERSISTENT_MESSAGE_LEVELS:
            msg = 'Test {} - {}'.format(level, datetime.datetime.now())
            messages.add_message(self.client, level, msg)
            result = Message.objects.get(level=level)
            self.assertEqual(result.message, msg)
            self.assertEqual(result.user, user)
            self.assertEqual(result.extra_tags, u'')
            self.assertIsNone(result.expires)
            self.assertIsNotNone(result.created)
            self.assertFalse(result.read)

    def test_mark_as_read(self):
        """Test the basic messaging"""
        self.client.login(username=self._get_user().username, password='password')
        messages.add_message(self.client, WARNING_PERSISTENT, "Warning..")
        result = Message.objects.all()[0]
        self.assertFalse(result.read)
        url = reverse('messages:message_mark_read', kwargs={'message_id': result.id})
        self.client.get(url)

        result = Message.objects.all()[0]
        self.assertTrue(result.read)

    def test_for_other_user(self):
        """Test the basic message for another user"""
        self.client.login(username=self._get_user().username, password='password')
        user2 = self._get_user(username="john")

        messages.add_message(self.client, WARNING_PERSISTENT, "Warning..", user=user2)
        result = Message.objects.all()[0]
        self.assertEqual(result.user, user2)

    def test_mark_message_read_for_other_user(self):
        """Test the basic message for another user"""
        res = self.client.login(username=self._get_user().username, password='password')
        user2 = self._get_user(username="john")
        messages.add_message(self.client, WARNING_PERSISTENT, "Warning..", user=user2)
        result = Message.objects.all()[0]
        self.assertEqual(result.user, user2)
        url = reverse('messages:message_mark_read', kwargs={'message_id': result.id})
        self.client.get(url)
        result = Message.objects.all()[0]
        self.assertFalse(result.read)

    def test_storages__get(self):
        """Unit test for storages.PersistentStorage._get, which gave bugs
        with Django 2.0"""
        rf = RequestFactory()
        req = rf.get("/")
        req.user = self._get_user(username="foo")

        ps = PersistentStorage(req)
        no_called = []
        def _patched_queryset(*args, **kw):
            no_called.append(1)
        ps._message_queryset = _patched_queryset
        ps._get()
        self.assertEquals(no_called[0], 1)

    def test_delete(self):
        user = self._get_user()
        self.client.login(username=user.username, password='password')
        messages.add_message(self.client, WARNING_PERSISTENT, "Warning Test")
        self.assertEquals(Message.objects.count(), 1)
        Message.objects.filter(user=user).first().delete()
        self.assertEquals(Message.objects.count(), 0)

    @mock.patch.object(Collector, 'can_fast_delete')
    def test_delete_user_complex_model(self, method_mock):
        method_mock.return_value = False
        user = self._get_user()
        self.client.login(username=user.username, password='password')

        # Create duplicated messages
        messages.add_message(self.client, WARNING_PERSISTENT, "Warning Test")
        messages.add_message(self.client, WARNING_PERSISTENT, "Warning Test")
        self.assertEquals(Message.objects.count(), 2)

        # User cascade deletes Message
        user.delete()
        self.assertEquals(Message.objects.count(), 0)

@@ -4681,17 +4681,16 @@
 ertEqual
-s
 (no_call
@@ -4924,33 +4924,32 @@
 self.assertEqual
-s
 (Message.objects
@@ -5036,33 +5036,32 @@
 self.assertEqual
-s
 (Message.objects
@@ -5540,33 +5540,32 @@
 self.assertEqual
-s
 (Message.objects
@@ -5663,17 +5663,16 @@
 ertEqual
-s
 (Message

replace deprecated assertEquals with assertEqual