from django.test import TestCase
from django.contrib.auth import get_user_model
from rest_framework.test import APIClient
from rest_framework import status
from django.urls import reverse
from follows.models import FollowCategory

User = get_user_model()


class CategoryTestCase(TestCase):
    def setUp(self):
        self.client = APIClient()
        self.user = User.objects.create_user(
            username='testuser',
            email='test@example.com',
            password='testpass123'
        )
        self.user2 = User.objects.create_user(
            username='user2',
            email='user2@example.com',
            password='user2pass123'
        )
        self.category_data = {
            'title': 'Test Category',
            'description': 'Test description'
        }

    def test_create_category(self):
        """Test creating a category"""
        self.client.force_authenticate(user=self.user)
        response = self.client.post(reverse('create_category'), self.category_data)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(response.data['title'], 'Test Category')

    def test_create_category_unauthenticated(self):
        """Test creating a category without authentication"""
        response = self.client.post(reverse('create_category'), self.category_data)
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)

    def test_list_categories(self):
        """Test listing categories"""
        self.client.force_authenticate(user=self.user)
        response = self.client.get(reverse('list_categories'))
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_category_detail(self):
        """Test viewing category details"""
        from categories.models import Category
        category = Category.objects.create(
            title='Test Category',
            description='Test description',
            created_by=self.user
        )
        self.client.force_authenticate(user=self.user)
        response = self.client.get(reverse('category_detail', args=[category.id]))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['title'], 'Test Category')

    def test_update_category(self):
        """Test updating a category"""
        from categories.models import Category
        category = Category.objects.create(
            title='Test Category',
            description='Test description',
            created_by=self.user
        )
        self.client.force_authenticate(user=self.user)
        update_data = {'title': 'Updated Category'}
        response = self.client.put(reverse('update_category', args=[category.id]), update_data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['title'], 'Updated Category')

    def test_update_category_unauthorized(self):
        """Test updating a category by non-creator"""
        from categories.models import Category
        category = Category.objects.create(
            title='Test Category',
            description='Test description',
            created_by=self.user
        )
        self.client.force_authenticate(user=self.user2)
        update_data = {'title': 'Updated Category'}
        response = self.client.put(reverse('update_category', args=[category.id]), update_data)
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

    def test_delete_category(self):
        """Test deleting a category"""
        from categories.models import Category
        category = Category.objects.create(
            title='Test Category',
            description='Test description',
            created_by=self.user
        )
        self.client.force_authenticate(user=self.user)
        response = self.client.delete(reverse('delete_category', args=[category.id]))
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)

    def test_delete_category_unauthorized(self):
        """Test deleting a category by non-creator"""
        from categories.models import Category
        category = Category.objects.create(
            title='Test Category',
            description='Test description',
            created_by=self.user
        )
        self.client.force_authenticate(user=self.user2)
        response = self.client.delete(reverse('delete_category', args=[category.id]))
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

    def test_follow_category(self):
        """Test following a category"""
        from categories.models import Category
        category = Category.objects.create(
            title='Test Category',
            description='Test description',
            created_by=self.user
        )
        self.client.force_authenticate(user=self.user2)
        response = self.client.post(reverse('follow_category', args=[category.id]))
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertTrue(FollowCategory.objects.filter(user=self.user2, category=category).exists())

    def test_follow_category_already_following(self):
        """Test following a category already followed"""
        from categories.models import Category
        category = Category.objects.create(
            title='Test Category',
            description='Test description',
            created_by=self.user
        )
        FollowCategory.objects.create(user=self.user2, category=category)
        self.client.force_authenticate(user=self.user2)
        response = self.client.post(reverse('follow_category', args=[category.id]))
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

    def test_unfollow_category(self):
        """Test unfollowing a category"""
        from categories.models import Category
        category = Category.objects.create(
            title='Test Category',
            description='Test description',
            created_by=self.user
        )
        FollowCategory.objects.create(user=self.user2, category=category)
        self.client.force_authenticate(user=self.user2)
        response = self.client.delete(reverse('unfollow_category', args=[category.id]))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertFalse(FollowCategory.objects.filter(user=self.user2, category=category).exists())

    def test_unfollow_category_not_following(self):
        """Test unfollowing a category not followed"""
        from categories.models import Category
        category = Category.objects.create(
            title='Test Category',
            description='Test description',
            created_by=self.user
        )
        self.client.force_authenticate(user=self.user2)
        response = self.client.delete(reverse('unfollow_category', args=[category.id]))
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)