from django.test import TestCase
from django.contrib.auth import get_user_model
from rest_framework.test import APITestCase, APIClient
from rest_framework import status
from rest_framework_simplejwt.tokens import RefreshToken
from .models import UserProfile
from apps.companies.models import Company
from apps.permissions.models import Permission, Role, UserCompanyRole

User = get_user_model()


class UserProfileSecurityTestCase(APITestCase):
    """Test user profile security and permissions"""
    
    def setUp(self):
        """Set up test data"""
        # Create super admin
        self.super_admin = User.objects.create_user(
            email='superadmin@test.com',
            username='superadmin',
            password='password123',
            user_type='super_admin'
        )
        self.super_admin.is_superuser = True
        self.super_admin.is_active = True  # Activate the user
        self.super_admin.save()
        
        # Create company
        self.company = Company.objects.create(
            name='Test Company',
            phone='+1234567890',
            office_time='9 AM - 6 PM',
            timezone='UTC'
        )
        
        # Create regular users
        self.user1 = User.objects.create_user(
            email='user1@test.com',
            username='user1',
            password='password123'
        )
        self.user1.is_active = True  # Activate the user
        self.user1.save()
        
        self.user2 = User.objects.create_user(
            email='user2@test.com',
            username='user2',
            password='password123'
        )
        self.user2.is_active = True  # Activate the user
        self.user2.save()
        
        # Add users to company
        self.user1.companies.add(self.company)
        self.user1.active_company = self.company
        self.user1.save()
        
        self.user2.companies.add(self.company)
        self.user2.active_company = self.company
        self.user2.save()
        
        # Create user profiles
        self.profile1 = UserProfile.objects.create(
            user=self.user1,
            first_name='John',
            last_name='Doe'
        )
        self.profile2 = UserProfile.objects.create(
            user=self.user2,
            first_name='Jane',
            last_name='Smith'
        )
        
        # Create permissions
        self.view_users_perm = Permission.objects.create(
            name='View Users',
            codename='view_users'
        )
        self.manage_users_perm = Permission.objects.create(
            name='Manage Users',
            codename='manage_users'
        )
        
        # Create role with permissions
        self.admin_role = Role.objects.create(
            name='Company Admin',
            description='Company administrator',
            company=self.company
        )
        self.admin_role.permissions.add(
            self.view_users_perm,
            self.manage_users_perm
        )
        
        # Assign role to user1
        UserCompanyRole.objects.create(
            user=self.user1,
            company=self.company,
            role=self.admin_role
        )
        
        # Setup API clients
        self.super_client = APIClient()
        self.user1_client = APIClient()
        self.user2_client = APIClient()
        
        # Get tokens
        super_refresh = RefreshToken.for_user(self.super_admin)
        user1_refresh = RefreshToken.for_user(self.user1)
        user2_refresh = RefreshToken.for_user(self.user2)
        
        self.super_client.credentials(HTTP_AUTHORIZATION=f'Bearer {super_refresh.access_token}')
        self.user1_client.credentials(HTTP_AUTHORIZATION=f'Bearer {user1_refresh.access_token}')
        self.user2_client.credentials(HTTP_AUTHORIZATION=f'Bearer {user2_refresh.access_token}')
    
    def test_super_admin_can_view_all_profiles(self):
        """Super admin should be able to view all user profiles"""
        response = self.super_client.get('/api/user-profile/')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        
        # Debug: Print response structure
        print(f"Response status: {response.status_code}")
        print(f"Response data keys: {response.data.keys() if hasattr(response.data, 'keys') else 'No keys'}")
        print(f"Response data type: {type(response.data)}")
        print(f"Response data: {response.data}")
        
        # Should see both profiles
        if hasattr(response.data, 'keys') and 'results' in response.data:
            usernames = [profile['user']['username'] for profile in response.data['results']]
        else:
            # Handle case where response.data is a list directly
            usernames = [profile['user']['username'] for profile in response.data]
        
        self.assertIn('user1', usernames)
        self.assertIn('user2', usernames)
    
    def test_regular_user_cannot_view_profiles_without_permission(self):
        """Regular user without view_users permission should be blocked"""
        # Remove view_users permission from role
        self.admin_role.permissions.remove(self.view_users_perm)
        
        response = self.user1_client.get('/api/user-profile/')
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
    
    def test_regular_user_can_view_profiles_with_permission(self):
        """Regular user with view_users permission should see company profiles"""
        response = self.user1_client.get('/api/user-profile/')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        
        # Should only see profiles from same company
        usernames = [profile['user']['username'] for profile in response.data['results']]
        self.assertIn('user1', usernames)
        self.assertIn('user2', usernames)
    
    def test_user_can_view_own_profile(self):
        """User should be able to view their own profile regardless of permissions"""
        # Remove all permissions from role
        self.admin_role.permissions.clear()
        
        response = self.user1_client.get(f'/api/user-profile/{self.user1.username}/')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['user']['username'], 'user1')
    
    def test_user_cannot_view_other_profiles_without_permission(self):
        """User without view_users permission cannot view other profiles"""
        # Remove view_users permission from role
        self.admin_role.permissions.remove(self.view_users_perm)
        
        response = self.user1_client.get(f'/api/user-profile/{self.user2.username}/')
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
    
    def test_user_can_view_other_profiles_with_permission(self):
        """User with view_users permission can view other company profiles"""
        response = self.user1_client.get(f'/api/user-profile/{self.user2.username}/')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['user']['username'], 'user2')
    
    def test_super_admin_can_edit_any_profile(self):
        """Super admin should be able to edit any profile"""
        data = {'first_name': 'Updated Name'}
        
        response = self.super_client.patch(f'/api/user-profile/{self.user1.username}/', data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        
        self.profile1.refresh_from_db()
        self.assertEqual(self.profile1.first_name, 'Updated Name')
    
    def test_regular_user_cannot_edit_other_profiles_without_permission(self):
        """Regular user without manage_users permission cannot edit other profiles"""
        # Remove manage_users permission from role
        self.admin_role.permissions.remove(self.manage_users_perm)
        
        data = {'first_name': 'Unauthorized Edit'}
        
        response = self.user1_client.patch(f'/api/user-profile/{self.user2.username}/', data)
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
        
        # Profile should not be changed
        self.profile2.refresh_from_db()
        self.assertEqual(self.profile2.first_name, 'Jane')
    
    def test_regular_user_can_edit_other_profiles_with_permission(self):
        """Regular user with manage_users permission can edit other profiles"""
        data = {'first_name': 'Authorized Edit'}
        
        response = self.user1_client.patch(f'/api/user-profile/{self.user2.username}/', data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        
        self.profile2.refresh_from_db()
        self.assertEqual(self.profile2.first_name, 'Authorized Edit')
    
    def test_user_can_edit_own_profile(self):
        """User should be able to edit their own profile regardless of permissions"""
        # Remove all permissions from role
        self.admin_role.permissions.clear()
        
        data = {'first_name': 'Self Edit'}
        
        response = self.user1_client.patch(f'/api/user-profile/{self.user1.username}/', data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        
        self.profile1.refresh_from_db()
        self.assertEqual(self.profile1.first_name, 'Self Edit')
    
    def test_company_filtering_works(self):
        """Users should only see profiles from their active company"""
        # Create another company with different users
        other_company = Company.objects.create(
            name='Other Company',
            phone='+9876543210',
            office_time='8 AM - 5 PM',
            timezone='UTC'
        )
        
        other_user = User.objects.create_user(
            email='other@test.com',
            username='otheruser',
            password='password123'
        )
        other_user.companies.add(other_company)
        other_user.active_company = other_company
        other_user.save()
        
        other_profile = UserProfile.objects.create(
            user=other_user,
            first_name='Other',
            last_name='User'
        )
        
        # User1 should only see profiles from their company
        response = self.user1_client.get('/api/user-profile/')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        
        usernames = [profile['user']['username'] for profile in response.data['results']]
        self.assertIn('user1', usernames)
        self.assertIn('user2', usernames)
        self.assertNotIn('otheruser', usernames)
    
    def test_super_admin_sees_all_profiles_regardless_of_company(self):
        """Super admin should see all profiles from all companies"""
        # Create another company with different users
        other_company = Company.objects.create(
            name='Other Company',
            phone='+9876543210',
            office_time='8 AM - 5 PM',
            timezone='UTC'
        )
        
        other_user = User.objects.create_user(
            email='other@test.com',
            username='otheruser',
            password='password123'
        )
        other_user.companies.add(other_company)
        other_user.active_company = other_company
        other_user.save()
        
        other_profile = UserProfile.objects.create(
            user=other_user,
            first_name='Other',
            last_name='User'
        )
        
        # Super admin should see all profiles
        response = self.super_client.get('/api/user-profile/')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        
        usernames = [profile['user']['username'] for profile in response.data['results']]
        self.assertIn('user1', usernames)
        self.assertIn('user2', usernames)
        self.assertIn('otheruser', usernames)
