from django.urls import reverse

from misago.admin.testutils import AdminTestCase
from misago.categories.models import Category
from misago.threads import testutils
from misago.threads.models import Attachment, AttachmentType


class AttachmentAdminViewsTests(AdminTestCase):
    def setUp(self):
        super(AttachmentAdminViewsTests, self).setUp()

        self.category = Category.objects.get(slug='first-category')
        self.post = testutils.post_thread(category=self.category).first_post

        self.filetype = AttachmentType.objects.order_by('id').first()

        self.admin_link = reverse('misago:admin:system:attachments:index')

    def mock_attachment(self, post=None, file=None, image=None, thumbnail=None):
        return Attachment.objects.create(
            secret=Attachment.generate_new_secret(),
            filetype=self.filetype,
            post=post,
            size=1000,
            uploader=self.user,
            uploader_name=self.user.username,
            uploader_slug=self.user.slug,
            filename='testfile_{}.zip'.format(Attachment.objects.count() + 1),
            file=None,
            image=None,
            thumbnail=None,
        )

    def test_link_registered(self):
        """admin nav contains attachments link"""
        response = self.client.get(reverse('misago:admin:system:settings:index'))
        self.assertContains(response, self.admin_link)

    def test_list_view(self):
        """attachments list returns 200 and renders all attachments"""
        final_link = self.client.get(self.admin_link)['location']

        response = self.client.get(final_link)
        self.assertEqual(response.status_code, 200)

        attachments = [
            self.mock_attachment(self.post, file='somefile.pdf'),
            self.mock_attachment(image='someimage.jpg'),
            self.mock_attachment(
                self.post,
                image='somelargeimage.png',
                thumbnail='somethumb.png',
            ),
        ]

        response = self.client.get(final_link)
        self.assertEqual(response.status_code, 200)

        for attachment in attachments:
            delete_link = reverse(
                'misago:admin:system:attachments:delete', kwargs={
                    'pk': attachment.pk,
                }
            )
            self.assertContains(response, attachment.filename)
            self.assertContains(response, delete_link)
            self.assertContains(response, attachment.get_absolute_url())
            self.assertContains(response, attachment.uploader.username)
            self.assertContains(response, attachment.uploader.get_absolute_url())

            if attachment.thumbnail:
                self.assertContains(response, attachment.get_thumbnail_url())

    def test_delete_multiple(self):
        """mass delete tool on list works"""
        attachments = [
            self.mock_attachment(self.post, file='somefile.pdf'),
            self.mock_attachment(image='someimage.jpg'),
            self.mock_attachment(
                self.post,
                image='somelargeimage.png',
                thumbnail='somethumb.png',
            ),
        ]

        self.post.attachments_cache = [{'id': attachments[-1].pk}]
        self.post.save()

        response = self.client.post(
            self.admin_link,
            data={
                'action': 'delete',
                'selected_items': [a.pk for a in attachments],
            }
        )
        self.assertEqual(response.status_code, 302)

        self.assertEqual(Attachment.objects.count(), 0)

        # assert attachments were removed from post's cache
        attachments_cache = self.category.post_set.get(pk=self.post.pk).attachments_cache
        self.assertIsNone(attachments_cache)

    def test_delete_view(self):
        """delete attachment view has no showstoppers"""
        attachment = self.mock_attachment(self.post)
        self.post.attachments_cache = [
            {
                'id': attachment.pk + 1
            },
            {
                'id': attachment.pk
            },
            {
                'id': attachment.pk + 2
            },
        ]
        self.post.save()

        action_link = reverse(
            'misago:admin:system:attachments:delete', kwargs={
                'pk': attachment.pk,
            }
        )

        response = self.client.post(action_link)
        self.assertEqual(response.status_code, 302)

        # clean alert about item, grab final list url
        final_link = self.client.get(self.admin_link)['location']

        response = self.client.get(final_link)
        self.assertEqual(response.status_code, 200)
        self.assertNotContains(response, action_link)

        # assert it was removed from post's attachments cache
        attachments_cache = self.category.post_set.get(pk=self.post.pk).attachments_cache
        self.assertEqual(
            attachments_cache, [
                {
                    'id': attachment.pk + 1,
                },
                {
                    'id': attachment.pk + 2,
                },
            ]
        )
