from django.urls import reverse

from misago.admin.testutils import AdminTestCase
from misago.categories.models import Category

from .. import testutils
from ..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,
            uploader_ip='127.0.0.1',
            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}
        ])