from http import HTTPStatus
import shutil
import tempfile

from django.test import TestCase, Client, override_settings
from django.contrib.auth import get_user_model
from django.urls import reverse
from django.core.files.uploadedfile import SimpleUploadedFile
from django.conf import settings

from ..models import Post, Group, Comment

User = get_user_model()


@override_settings(MEDIA_ROOT=tempfile.mkdtemp(dir=settings.BASE_DIR))
class PostFormTests(TestCase):

    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.user = User.objects.create_user(username='TestUser')
        cls.group = Group.objects.create(
            title='Тестовое имя группы',
            slug='test_group',
            description='Тестовое описание группы',
        )

    def setUp(self):
        self.authorized_client = Client()
        self.authorized_client.force_login(self.user)

    @classmethod
    def tearDownClass(self) -> None:
        shutil.rmtree(settings.MEDIA_ROOT, ignore_errors=True)
        super().tearDownClass()

    def test_create_post(self):
        '''При правильном заполнении формы создается новая запись'''
        small_gif = (
            b'\x47\x49\x46\x38\x39\x61\x02\x00'
            b'\x01\x00\x80\x00\x00\x00\x00\x00'
            b'\xFF\xFF\xFF\x21\xF9\x04\x00\x00'
            b'\x00\x00\x00\x2C\x00\x00\x00\x00'
            b'\x02\x00\x01\x00\x00\x02\x02\x0C'
            b'\x0A\x00\x3B'
        )
        uploaded = SimpleUploadedFile(
            name='small.gif',
            content=small_gif,
            content_type='image/gif'
        )
        form_data = {
            'group': self.group.id,
            'text': 'Тестовый текст',
            'image': uploaded
        }
        response = self.authorized_client.post(
            reverse('new_post'),
            data=form_data,
            follow=True
        )
        self.assertRedirects(response, reverse('index'))
        self.assertEqual(response.status_code, HTTPStatus.OK)
        self.assertEqual(Post.objects.count(), 1)
        self.assertTrue(Post.objects.filter(
            text=form_data['text'],
            group=form_data['group'],
            image=f'posts/{uploaded.name}'
        ).exists())

    def test_edit_post(self):
        '''При правильном заполнении формы запись обновляется; новая запись
        не появляется.'''
        post = Post.objects.create(
            text='Тестовый текст',
            author=self.user
        )
        form_data = {
            'text': 'Новый текст'
        }
        response = self.authorized_client.post(
            reverse('post_edit', kwargs={'username': self.user.username,
                                         'post_id': post.id}),
            data=form_data,
            follow=True
        )
        self.assertRedirects(
            response,
            reverse('post',
                    kwargs={'username': self.user.username,
                            'post_id': post.id})
        )

        self.assertEqual(response.status_code, HTTPStatus.OK)
        self.assertEqual(Post.objects.count(), 1)
        self.assertTrue(Post.objects.filter(text=form_data['text']).exists())

    def test_create_comment(self):
        '''При правильном заполнении формы создается новый комментарий'''
        # Теста на создание от гостя нет, есть тест на редирект в test_urls
        post = Post.objects.create(
            text='Тестовый текст',
            author=self.user
        )
        form_data = {
            'text': 'Тестовый текст комментария'
        }
        response = self.authorized_client.post(
            reverse('add_comment', kwargs={'username': self.user.username,
                                           'post_id': post.id}),
            data=form_data,
            follow=True
        )
        self.assertRedirects(
            response,
            reverse('post',
                    kwargs={'username': self.user.username,
                            'post_id': post.id})
        )
        self.assertEqual(response.status_code, HTTPStatus.OK)
        self.assertEqual(Comment.objects.count(), 1)
        self.assertTrue(
            Comment.objects.filter(text=form_data['text']).exists()
        )
