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 FollowUser

User = get_user_model()


class UserTestCase(TestCase):
    def setUp(self):
        self.client = APIClient()
        self.user_data = {
            'username': 'testuser',
            'email': 'test@example.com',
            'password': 'testpass123',
            'password_confirm': 'testpass123',
            'first_name': 'Test',
            'last_name': 'User'
        }
        self.user = User.objects.create_user(
            username='existinguser',
            email='existing@example.com',
            password='existingpass123'
        )
        self.user2 = User.objects.create_user(
            username='user2',
            email='user2@example.com',
            password='user2pass123'
        )

    def test_user_registration(self):
        """Test user registration"""
        response = self.client.post(reverse('register'), self.user_data)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertIn('auth_token', response.cookies)
        self.assertIn('user', response.data)

    def test_user_registration_password_mismatch(self):
        """Test user registration with password mismatch"""
        data = self.user_data.copy()
        data['password_confirm'] = 'different'
        response = self.client.post(reverse('register'), data)
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

    def test_user_login(self):
        """Test user login"""
        login_data = {
            'identifier': 'existinguser',
            'password': 'existingpass123'
        }
        response = self.client.post(reverse('login'), login_data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertIn('auth_token', response.cookies)

    def test_user_login_invalid_credentials(self):
        """Test user login with invalid credentials"""
        login_data = {
            'identifier': 'existinguser',
            'password': 'wrongpassword'
        }
        response = self.client.post(reverse('login'), login_data)
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

    def test_user_profile(self):
        """Test getting user profile"""
        self.client.force_authenticate(user=self.user)
        response = self.client.get(reverse('profile'))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['username'], 'existinguser')

    def test_user_profile_update(self):
        """Test updating user profile"""
        self.client.force_authenticate(user=self.user)
        update_data = {'bio': 'New bio', 'first_name': 'Updated'}
        response = self.client.put(reverse('profile'), update_data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['bio'], 'New bio')

    def test_follow_user(self):
        """Test following a user"""
        self.client.force_authenticate(user=self.user)
        response = self.client.post(reverse('follow_user', args=[self.user2.id]))
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertTrue(FollowUser.objects.filter(follower=self.user, followed=self.user2).exists())

    def test_follow_user_self(self):
        """Test following oneself (should fail)"""
        self.client.force_authenticate(user=self.user)
        response = self.client.post(reverse('follow_user', args=[self.user.id]))
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

    def test_follow_user_already_following(self):
        """Test following a user already followed"""
        FollowUser.objects.create(follower=self.user, followed=self.user2)
        self.client.force_authenticate(user=self.user)
        response = self.client.post(reverse('follow_user', args=[self.user2.id]))
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

    def test_unfollow_user(self):
        """Test unfollowing a user"""
        FollowUser.objects.create(follower=self.user, followed=self.user2)
        self.client.force_authenticate(user=self.user)
        response = self.client.delete(reverse('unfollow_user', args=[self.user2.id]))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertFalse(FollowUser.objects.filter(follower=self.user, followed=self.user2).exists())

    def test_unfollow_user_not_following(self):
        """Test unfollowing a user not followed"""
        self.client.force_authenticate(user=self.user)
        response = self.client.delete(reverse('unfollow_user', args=[self.user2.id]))
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

    def test_user_profile_view(self):
        """Test viewing another user's profile"""
        self.client.force_authenticate(user=self.user)
        response = self.client.get(reverse('user_profile', args=[self.user2.id]))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['username'], 'user2')

    def test_delete_account(self):
        """Test deleting user account (hard delete)"""
        self.client.force_authenticate(user=self.user)
        response = self.client.delete(reverse('delete_account'))
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)

        # Verify user is deleted
        self.assertFalse(User.objects.filter(id=self.user.id).exists())