"""
Unit tests for permission classes
Tests IsAuthenticatedAndActive, HasTenantAccess, IsViewerOrAbove, IsEditorOrAbove, IsAdminOrOwner
"""
from django.test import TestCase
from rest_framework.test import APIRequestFactory
from rest_framework.views import APIView
from igny8_core.api.permissions import (
    IsAuthenticatedAndActive, HasTenantAccess, IsViewerOrAbove,
    IsEditorOrAbove, IsAdminOrOwner
)
from igny8_core.auth.models import User, Account, Plan


class PermissionsTestCase(TestCase):
    """Test cases for permission classes"""
    
    def setUp(self):
        """Set up test fixtures"""
        self.factory = APIRequestFactory()
        self.view = APIView()
        
        # Create test plan
        self.plan = Plan.objects.create(
            name="Test Plan",
            slug="test-plan",
            price=0,
            credits_per_month=1000
        )
        
        # Create owner user first (Account needs owner)
        self.owner_user = User.objects.create_user(
            username='owner',
            email='owner@test.com',
            password='testpass123',
            role='owner'
        )
        
        # Create test account with owner
        self.account = Account.objects.create(
            name="Test Account",
            slug="test-account",
            plan=self.plan,
            owner=self.owner_user
        )
        
        # Update owner user to have account
        self.owner_user.account = self.account
        self.owner_user.save()
        
        self.admin_user = User.objects.create_user(
            username='admin',
            email='admin@test.com',
            password='testpass123',
            role='admin',
            account=self.account
        )
        
        self.editor_user = User.objects.create_user(
            username='editor',
            email='editor@test.com',
            password='testpass123',
            role='editor',
            account=self.account
        )
        
        self.viewer_user = User.objects.create_user(
            username='viewer',
            email='viewer@test.com',
            password='testpass123',
            role='viewer',
            account=self.account
        )
        
        # Create another account for tenant isolation testing
        self.other_owner = User.objects.create_user(
            username='other_owner',
            email='other_owner@test.com',
            password='testpass123',
            role='owner'
        )
        
        self.other_account = Account.objects.create(
            name="Other Account",
            slug="other-account",
            plan=self.plan,
            owner=self.other_owner
        )
        
        self.other_owner.account = self.other_account
        self.other_owner.save()
        
        self.other_user = User.objects.create_user(
            username='other',
            email='other@test.com',
            password='testpass123',
            role='owner',
            account=self.other_account
        )
    
    def test_is_authenticated_and_active_authenticated(self):
        """Test IsAuthenticatedAndActive allows authenticated users"""
        permission = IsAuthenticatedAndActive()
        request = self.factory.get('/test/')
        request.user = self.owner_user
        
        result = permission.has_permission(request, self.view)
        self.assertTrue(result)
    
    def test_is_authenticated_and_active_unauthenticated(self):
        """Test IsAuthenticatedAndActive denies unauthenticated users"""
        permission = IsAuthenticatedAndActive()
        request = self.factory.get('/test/')
        request.user = None
        
        result = permission.has_permission(request, self.view)
        self.assertFalse(result)
    
    def test_is_authenticated_and_active_inactive_user(self):
        """Test IsAuthenticatedAndActive denies inactive users"""
        permission = IsAuthenticatedAndActive()
        self.owner_user.is_active = False
        self.owner_user.save()
        
        request = self.factory.get('/test/')
        request.user = self.owner_user
        
        result = permission.has_permission(request, self.view)
        self.assertFalse(result)
    
    def test_has_tenant_access_same_account(self):
        """Test HasTenantAccess allows users from same account"""
        permission = HasTenantAccess()
        request = self.factory.get('/test/')
        request.user = self.owner_user
        request.account = self.account
        
        result = permission.has_permission(request, self.view)
        self.assertTrue(result)
    
    def test_has_tenant_access_different_account(self):
        """Test HasTenantAccess denies users from different account"""
        permission = HasTenantAccess()
        request = self.factory.get('/test/')
        request.user = self.owner_user
        request.account = self.other_account
        
        result = permission.has_permission(request, self.view)
        self.assertFalse(result)
    
    def test_has_tenant_access_admin_bypass(self):
        """Test HasTenantAccess allows admin/developer to bypass"""
        permission = HasTenantAccess()
        request = self.factory.get('/test/')
        request.user = self.admin_user
        request.account = self.other_account  # Different account
        
        result = permission.has_permission(request, self.view)
        self.assertTrue(result)  # Admin should bypass
    
    def test_has_tenant_access_system_account(self):
        """Test HasTenantAccess allows system account users to bypass"""
        # Create system account owner
        system_owner = User.objects.create_user(
            username='system_owner_test',
            email='system_owner_test@test.com',
            password='testpass123',
            role='owner'
        )
        
        # Create system account
        system_account = Account.objects.create(
            name="AWS Admin",
            slug="aws-admin",
            plan=self.plan,
            owner=system_owner
        )
        
        system_owner.account = system_account
        system_owner.save()
        
        system_user = User.objects.create_user(
            username='system',
            email='system@test.com',
            password='testpass123',
            role='viewer',
            account=system_account
        )
        
        permission = HasTenantAccess()
        request = self.factory.get('/test/')
        request.user = system_user
        request.account = self.account  # Different account
        
        result = permission.has_permission(request, self.view)
        self.assertTrue(result)  # System account user should bypass
    
    def test_is_viewer_or_above_viewer(self):
        """Test IsViewerOrAbove allows viewer role"""
        permission = IsViewerOrAbove()
        request = self.factory.get('/test/')
        request.user = self.viewer_user
        
        result = permission.has_permission(request, self.view)
        self.assertTrue(result)
    
    def test_is_viewer_or_above_editor(self):
        """Test IsViewerOrAbove allows editor role"""
        permission = IsViewerOrAbove()
        request = self.factory.get('/test/')
        request.user = self.editor_user
        
        result = permission.has_permission(request, self.view)
        self.assertTrue(result)
    
    def test_is_viewer_or_above_admin(self):
        """Test IsViewerOrAbove allows admin role"""
        permission = IsViewerOrAbove()
        request = self.factory.get('/test/')
        request.user = self.admin_user
        
        result = permission.has_permission(request, self.view)
        self.assertTrue(result)
    
    def test_is_viewer_or_above_owner(self):
        """Test IsViewerOrAbove allows owner role"""
        permission = IsViewerOrAbove()
        request = self.factory.get('/test/')
        request.user = self.owner_user
        
        result = permission.has_permission(request, self.view)
        self.assertTrue(result)
    
    def test_is_editor_or_above_viewer_denied(self):
        """Test IsEditorOrAbove denies viewer role"""
        permission = IsEditorOrAbove()
        request = self.factory.get('/test/')
        request.user = self.viewer_user
        
        result = permission.has_permission(request, self.view)
        self.assertFalse(result)
    
    def test_is_editor_or_above_editor_allowed(self):
        """Test IsEditorOrAbove allows editor role"""
        permission = IsEditorOrAbove()
        request = self.factory.get('/test/')
        request.user = self.editor_user
        
        result = permission.has_permission(request, self.view)
        self.assertTrue(result)
    
    def test_is_editor_or_above_admin_allowed(self):
        """Test IsEditorOrAbove allows admin role"""
        permission = IsEditorOrAbove()
        request = self.factory.get('/test/')
        request.user = self.admin_user
        
        result = permission.has_permission(request, self.view)
        self.assertTrue(result)
    
    def test_is_admin_or_owner_viewer_denied(self):
        """Test IsAdminOrOwner denies viewer role"""
        permission = IsAdminOrOwner()
        request = self.factory.get('/test/')
        request.user = self.viewer_user
        
        result = permission.has_permission(request, self.view)
        self.assertFalse(result)
    
    def test_is_admin_or_owner_editor_denied(self):
        """Test IsAdminOrOwner denies editor role"""
        permission = IsAdminOrOwner()
        request = self.factory.get('/test/')
        request.user = self.editor_user
        
        result = permission.has_permission(request, self.view)
        self.assertFalse(result)
    
    def test_is_admin_or_owner_admin_allowed(self):
        """Test IsAdminOrOwner allows admin role"""
        permission = IsAdminOrOwner()
        request = self.factory.get('/test/')
        request.user = self.admin_user
        
        result = permission.has_permission(request, self.view)
        self.assertTrue(result)
    
    def test_is_admin_or_owner_owner_allowed(self):
        """Test IsAdminOrOwner allows owner role"""
        permission = IsAdminOrOwner()
        request = self.factory.get('/test/')
        request.user = self.owner_user
        
        result = permission.has_permission(request, self.view)
        self.assertTrue(result)
    
    def test_all_permissions_unauthenticated_denied(self):
        """Test all permissions deny unauthenticated users"""
        permissions = [
            IsAuthenticatedAndActive(),
            HasTenantAccess(),
            IsViewerOrAbove(),
            IsEditorOrAbove(),
            IsAdminOrOwner()
        ]
        
        request = self.factory.get('/test/')
        request.user = None
        
        for permission in permissions:
            result = permission.has_permission(request, self.view)
            self.assertFalse(result, f"{permission.__class__.__name__} should deny unauthenticated users")

