"""
Tests for Tenant Isolation.

Test Coverage:
- Tenant schema isolation
- Domain routing
- Cross-tenant access prevention
"""
import pytest
from django.db import connection
from django.contrib.auth import get_user_model

User = get_user_model()


@pytest.mark.django_db
class TestTenantIsolation:
    """Tests for tenant data isolation."""

    def test_public_schema_exists(self):
        """Test that public schema exists and is accessible."""
        from apps.core.tenant.models import Tenant, Domain
        
        # Public tenant should exist
        public_tenant = Tenant.objects.filter(schema_name='public').first()
        assert public_tenant is not None

    def test_tenant_has_domain(self):
        """Test that tenant has at least one domain."""
        from apps.core.tenant.models import Tenant, Domain
        
        public_tenant = Tenant.objects.filter(schema_name='public').first()
        if public_tenant:
            domains = Domain.objects.filter(tenant=public_tenant)
            assert domains.exists()

    def test_localhost_domain_exists(self):
        """Test that localhost domain is configured."""
        from apps.core.tenant.models import Domain
        
        localhost_domain = Domain.objects.filter(domain='localhost').first()
        assert localhost_domain is not None

    def test_schema_name_unique(self):
        """Test that schema names are unique."""
        from apps.core.tenant.models import Tenant
        from django.db import IntegrityError, transaction
        
        # Create first tenant
        tenant1 = Tenant.objects.create(
            schema_name='test_unique_schema',
            name='Test Tenant 1',
            slug='test-unique-schema-1'
        )
        
        try:
            # Try to create second tenant with same schema name
            with pytest.raises(IntegrityError):
                with transaction.atomic():
                    Tenant.objects.create(
                        schema_name='test_unique_schema',
                        name='Test Tenant 2',
                        slug='test-unique-schema-2'
                    )
        finally:
            # Cleanup
            tenant1.delete()

    def test_domain_unique(self):
        """Test that domains are unique."""
        from apps.core.tenant.models import Tenant, Domain
        from django.db import IntegrityError, transaction
        
        # Get or create a tenant
        tenant = Tenant.objects.filter(schema_name='public').first()
        
        # Create first domain
        domain1, created = Domain.objects.get_or_create(
            domain='unique-test.localhost',
            defaults={'tenant': tenant, 'is_primary': False}
        )
        
        try:
            # Try to create second domain with same value
            with pytest.raises(IntegrityError):
                with transaction.atomic():
                    Domain.objects.create(
                        domain='unique-test.localhost',
                        tenant=tenant,
                        is_primary=False
                    )
        finally:
            # Cleanup if we created it
            if created:
                domain1.delete()


@pytest.mark.django_db
class TestTenantModels:
    """Tests for Tenant model functionality."""

    def test_tenant_string_representation(self):
        """Test tenant string representation."""
        from apps.core.tenant.models import Tenant
        
        tenant = Tenant(name='Test Company', schema_name='test_company')
        
        # String representation should include name or schema_name
        str_repr = str(tenant)
        assert 'Test Company' in str_repr or 'test_company' in str_repr

    def test_domain_string_representation(self):
        """Test domain string representation."""
        from apps.core.tenant.models import Tenant, Domain
        
        tenant = Tenant(name='Test', schema_name='test')
        domain = Domain(domain='test.localhost', tenant=tenant)
        
        str_repr = str(domain)
        assert 'test.localhost' in str_repr

    def test_tenant_created_at_auto_set(self):
        """Test that created_at is automatically set."""
        from apps.core.tenant.models import Tenant
        from django.utils import timezone
        
        tenant = Tenant.objects.create(
            name='Auto Date Test',
            schema_name='auto_date_test',
            slug='auto-date-test'
        )
        
        assert tenant.created_at is not None
        assert tenant.created_at <= timezone.now()
        
        # Cleanup
        tenant.delete()


@pytest.mark.django_db
class TestTenantDomainRelation:
    """Tests for Tenant-Domain relationship."""

    def test_tenant_can_have_multiple_domains(self):
        """Test that a tenant can have multiple domains."""
        from apps.core.tenant.models import Tenant, Domain
        
        tenant = Tenant.objects.create(
            name='Multi Domain Test',
            schema_name='multi_domain_test',
            slug='multi-domain-test'
        )
        
        domain1 = Domain.objects.create(
            domain='multi1.localhost',
            tenant=tenant,
            is_primary=True
        )
        domain2 = Domain.objects.create(
            domain='multi2.localhost',
            tenant=tenant,
            is_primary=False
        )
        
        assert tenant.domains.count() == 2
        
        # Cleanup
        domain1.delete()
        domain2.delete()
        tenant.delete()

    def test_domain_belongs_to_tenant(self):
        """Test domain-tenant relationship."""
        from apps.core.tenant.models import Domain
        
        domain = Domain.objects.filter(domain='localhost').first()
        if domain:
            assert domain.tenant is not None
            assert domain.tenant.schema_name == 'public'

    def test_delete_tenant_cascades_domains(self):
        """Test that deleting tenant deletes its domains."""
        from apps.core.tenant.models import Tenant, Domain
        
        tenant = Tenant.objects.create(
            name='Cascade Test',
            schema_name='cascade_test',
            slug='cascade-test'
        )
        domain = Domain.objects.create(
            domain='cascade.localhost',
            tenant=tenant,
            is_primary=True
        )
        domain_id = domain.id
        
        # Delete tenant
        tenant.delete()
        
        # Domain should also be deleted
        assert not Domain.objects.filter(id=domain_id).exists()
