from unittest.mock import MagicMock, patch

from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
from django.test import TestCase

from .models import User, UserProfile
from .signals import create_default_groups


class SignalsTestCase(TestCase):
    def setUp(self):
        self.user = User.objects.create_user(
            username="testuser",
            email="testuser@example.com",
            password="password",
        )

    def test_create_user_profile(self):
        # Refresh user from database to ensure signals have been processed
        self.user.refresh_from_db()

        # Check if profile exists in database first
        profile_exists = UserProfile.objects.filter(user=self.user).exists()
        self.assertTrue(profile_exists, "UserProfile should be created by signals")

        # Now safely access the profile
        profile = UserProfile.objects.get(user=self.user)
        self.assertIsInstance(profile, UserProfile)

        # Test the reverse relationship
        self.assertTrue(hasattr(self.user, "profile"))
        # Test that we can access the profile through the user relationship
        user_profile = getattr(self.user, "profile", None)
        self.assertEqual(user_profile, profile)

    @patch("accounts.signals.requests.get")
    def test_create_user_profile_with_social_avatar(self, mock_get):
        # Mock the response from requests.get
        mock_response = MagicMock()
        mock_response.status_code = 200
        mock_response.content = b"fake-image-content"
        mock_get.return_value = mock_response

        # Create a social account for the user (we'll skip this test since socialaccount_set requires allauth setup)
        # This test would need proper allauth configuration to work
        self.skipTest("Requires proper allauth socialaccount setup")

    def test_save_user_profile(self):
        # Get the profile safely first
        profile = UserProfile.objects.get(user=self.user)
        profile.delete()

        # Refresh user to clear cached profile relationship
        self.user.refresh_from_db()

        # Check that profile no longer exists
        self.assertFalse(UserProfile.objects.filter(user=self.user).exists())

        # Trigger save to recreate profile via signal
        self.user.save()

        # Verify profile was recreated
        self.assertTrue(UserProfile.objects.filter(user=self.user).exists())
        new_profile = UserProfile.objects.get(user=self.user)
        self.assertIsInstance(new_profile, UserProfile)

    def test_sync_user_role_with_groups(self):
        self.user.role = User.Roles.MODERATOR
        self.user.save()
        self.assertTrue(self.user.groups.filter(name=User.Roles.MODERATOR).exists())
        self.assertTrue(self.user.is_staff)

        self.user.role = User.Roles.ADMIN
        self.user.save()
        self.assertFalse(self.user.groups.filter(name=User.Roles.MODERATOR).exists())
        self.assertTrue(self.user.groups.filter(name=User.Roles.ADMIN).exists())
        self.assertTrue(self.user.is_staff)

        self.user.role = User.Roles.SUPERUSER
        self.user.save()
        self.assertFalse(self.user.groups.filter(name=User.Roles.ADMIN).exists())
        self.assertTrue(self.user.groups.filter(name=User.Roles.SUPERUSER).exists())
        self.assertTrue(self.user.is_superuser)
        self.assertTrue(self.user.is_staff)

        self.user.role = User.Roles.USER
        self.user.save()
        self.assertFalse(self.user.groups.exists())
        self.assertFalse(self.user.is_superuser)
        self.assertFalse(self.user.is_staff)

    def test_create_default_groups(self):
        # Create some permissions for testing
        content_type = ContentType.objects.get_for_model(User)
        Permission.objects.create(
            codename="change_review",
            name="Can change review",
            content_type=content_type,
        )
        Permission.objects.create(
            codename="delete_review",
            name="Can delete review",
            content_type=content_type,
        )
        Permission.objects.create(
            codename="change_user",
            name="Can change user",
            content_type=content_type,
        )

        create_default_groups()

        moderator_group = Group.objects.get(name=User.Roles.MODERATOR)
        self.assertIsNotNone(moderator_group)
        self.assertTrue(moderator_group.permissions.filter(codename="change_review").exists())
        self.assertFalse(moderator_group.permissions.filter(codename="change_user").exists())

        admin_group = Group.objects.get(name=User.Roles.ADMIN)
        self.assertIsNotNone(admin_group)
        self.assertTrue(admin_group.permissions.filter(codename="change_review").exists())
        self.assertTrue(admin_group.permissions.filter(codename="change_user").exists())
