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

User = get_user_model()


class FollowTestCase(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.user3 = User.objects.create_user(
            username='user3',
            email='user3@example.com',
            password='user3pass123'
        )
        from categories.models import Category
        self.category = Category.objects.create(
            title='Test Category',
            description='Test description',
            created_by=self.user
        )

    def test_list_user_followers(self):
        """Test listing followers of a user"""
        from follows.models import FollowUser
        FollowUser.objects.create(follower=self.user2, followed=self.user)
        FollowUser.objects.create(follower=self.user3, followed=self.user)
        self.client.force_authenticate(user=self.user)
        response = self.client.get(reverse('list_user_followers', args=[self.user.id]))
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_list_user_following(self):
        """Test listing users that a user follows"""
        from follows.models import FollowUser
        FollowUser.objects.create(follower=self.user, followed=self.user2)
        FollowUser.objects.create(follower=self.user, followed=self.user3)
        self.client.force_authenticate(user=self.user)
        response = self.client.get(reverse('list_user_following', args=[self.user.id]))
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_list_category_followers(self):
        """Test listing followers of a category"""
        from follows.models import FollowCategory
        FollowCategory.objects.create(user=self.user2, category=self.category)
        FollowCategory.objects.create(user=self.user3, category=self.category)
        self.client.force_authenticate(user=self.user)
        response = self.client.get(reverse('list_category_followers', args=[self.category.id]))
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_list_user_followed_categories(self):
        """Test listing categories followed by a user"""
        from follows.models import FollowCategory
        from categories.models import Category
        category2 = Category.objects.create(
            title='Category 2',
            created_by=self.user2
        )
        FollowCategory.objects.create(user=self.user, category=self.category)
        FollowCategory.objects.create(user=self.user, category=category2)
        self.client.force_authenticate(user=self.user)
        response = self.client.get(reverse('list_user_followed_categories', args=[self.user.id]))
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_follow_user_unique_constraint(self):
        """Test that a user can only follow another user once"""
        from follows.models import FollowUser
        # First follow should succeed
        FollowUser.objects.create(follower=self.user, followed=self.user2)
        # Second follow should raise IntegrityError
        with self.assertRaises(Exception):
            FollowUser.objects.create(follower=self.user, followed=self.user2)

    def test_follow_category_unique_constraint(self):
        """Test that a user can only follow a category once"""
        from follows.models import FollowCategory
        # First follow should succeed
        FollowCategory.objects.create(user=self.user, category=self.category)
        # Second follow should raise IntegrityError
        with self.assertRaises(Exception):
            FollowCategory.objects.create(user=self.user, category=self.category)

    def test_follow_user_self_constraint(self):
        """Test that a user cannot follow themselves"""
        from follows.models import FollowUser
        # Following self should raise IntegrityError or validation error
        with self.assertRaises(Exception):
            FollowUser.objects.create(follower=self.user, followed=self.user)