"""
Notification Service Tests - Models.
"""
import pytest
from django.contrib.auth import get_user_model
from django.db import IntegrityError

from apps.core.tenant.models import Tenant
from apps.services.notification.models import (
    NotificationCategory,
    NotificationTemplate,
    Notification,
    NotificationLog,
    UserNotificationPreference,
    NotificationChannel,
    NotificationStatus,
    NotificationPriority,
)

User = get_user_model()


@pytest.fixture
def tenant(db):
    """Create a test tenant."""
    return Tenant.objects.create(
        name='Test Tenant',
        slug='test-tenant',
        schema_name='test_tenant',
    )


@pytest.fixture
def user(db, tenant):
    """Create a test user."""
    return User.objects.create_user(
        email='test@example.com',
        password='testpass123',
    )


@pytest.fixture
def category(db, tenant):
    """Create a test notification category."""
    return NotificationCategory.objects.create(
        tenant=tenant,
        name='transaction',
        label='تراکنش مالی',
        description='نوتیفیکیشن‌های مربوط به تراکنش‌ها',
        color='#10B981',
    )


@pytest.fixture
def template(db, tenant, category):
    """Create a test notification template."""
    return NotificationTemplate.objects.create(
        tenant=tenant,
        category=category,
        name='welcome_sms',
        title='خوش آمدید',
        channel=NotificationChannel.SMS,
        content='سلام {{ user_name }}! به {{ tenant_name }} خوش آمدید.',
        variables=['user_name', 'tenant_name'],
    )


@pytest.fixture
def notification(db, tenant, user, category, template):
    """Create a test notification."""
    return Notification.objects.create(
        tenant=tenant,
        user=user,
        category=category,
        template=template,
        channel=NotificationChannel.SMS,
        title='تست نوتیفیکیشن',
        content='این یک پیام تست است.',
        priority=NotificationPriority.NORMAL,
        status=NotificationStatus.PENDING,
    )


class TestNotificationCategory:
    """Tests for NotificationCategory model."""
    
    def test_create_category(self, tenant):
        """Test creating a notification category."""
        category = NotificationCategory.objects.create(
            tenant=tenant,
            name='system',
            label='سیستمی',
        )
        
        assert category.pk is not None
        assert category.name == 'system'
        assert category.label == 'سیستمی'
        assert category.is_active is True
        assert category.color == '#6B7280'
    
    def test_unique_name_per_tenant(self, tenant, category):
        """Test that category name is unique per tenant."""
        with pytest.raises(IntegrityError):
            NotificationCategory.objects.create(
                tenant=tenant,
                name='transaction',  # Same as fixture
                label='Another Label',
            )
    
    def test_str_representation(self, category):
        """Test string representation."""
        assert str(category) == 'تراکنش مالی'


class TestNotificationTemplate:
    """Tests for NotificationTemplate model."""
    
    def test_create_template(self, tenant, category):
        """Test creating a notification template."""
        template = NotificationTemplate.objects.create(
            tenant=tenant,
            category=category,
            name='test_template',
            title='تست',
            channel=NotificationChannel.EMAIL,
            subject='Test Subject',
            content='Hello {{ user_name }}!',
            variables=['user_name'],
        )
        
        assert template.pk is not None
        assert template.channel == NotificationChannel.EMAIL
        assert 'user_name' in template.variables
    
    def test_unique_name_per_tenant(self, tenant, template):
        """Test that template name is unique per tenant."""
        with pytest.raises(IntegrityError):
            NotificationTemplate.objects.create(
                tenant=tenant,
                name='welcome_sms',  # Same as fixture
                title='Another',
                channel=NotificationChannel.SMS,
                content='Test',
            )
    
    def test_str_representation(self, template):
        """Test string representation."""
        assert 'خوش آمدید' in str(template)
        assert 'SMS' in str(template)


class TestNotification:
    """Tests for Notification model."""
    
    def test_create_notification(self, tenant, user):
        """Test creating a notification."""
        notification = Notification.objects.create(
            tenant=tenant,
            user=user,
            channel=NotificationChannel.PANEL,
            title='تست',
            content='محتوای تست',
        )
        
        assert notification.pk is not None
        assert notification.status == NotificationStatus.PENDING
        assert notification.is_read is False
        assert notification.priority == NotificationPriority.NORMAL
    
    def test_uuid_primary_key(self, notification):
        """Test that notification uses UUID as primary key."""
        import uuid
        assert isinstance(notification.pk, uuid.UUID)
    
    def test_mark_as_read(self, notification):
        """Test marking notification as read."""
        assert notification.is_read is False
        assert notification.read_at is None
        
        notification.mark_as_read()
        
        assert notification.is_read is True
        assert notification.read_at is not None
        assert notification.status == NotificationStatus.READ
    
    def test_mark_as_read_idempotent(self, notification):
        """Test that mark_as_read is idempotent."""
        notification.mark_as_read()
        first_read_at = notification.read_at
        
        notification.mark_as_read()
        
        assert notification.read_at == first_read_at
    
    def test_str_representation(self, notification):
        """Test string representation."""
        assert 'تست نوتیفیکیشن' in str(notification)


class TestNotificationLog:
    """Tests for NotificationLog model."""
    
    def test_create_log(self, tenant, notification):
        """Test creating a notification log."""
        log = NotificationLog.objects.create(
            tenant=tenant,
            notification=notification,
            channel=NotificationChannel.SMS,
            status=NotificationStatus.SENT,
            provider_response={'message_id': '12345'},
        )
        
        assert log.pk is not None
        assert log.retry_count == 0
    
    def test_log_with_error(self, tenant, notification):
        """Test creating a log with error."""
        log = NotificationLog.objects.create(
            tenant=tenant,
            notification=notification,
            channel=NotificationChannel.SMS,
            status=NotificationStatus.FAILED,
            error_message='Connection timeout',
            retry_count=1,
        )
        
        assert log.status == NotificationStatus.FAILED
        assert log.error_message == 'Connection timeout'


class TestUserNotificationPreference:
    """Tests for UserNotificationPreference model."""
    
    def test_create_preference(self, tenant, user, category):
        """Test creating user preferences."""
        pref = UserNotificationPreference.objects.create(
            tenant=tenant,
            user=user,
            category=category,
            sms_enabled=True,
            email_enabled=False,
            panel_enabled=True,
        )
        
        assert pref.pk is not None
        assert pref.sms_enabled is True
        assert pref.email_enabled is False
    
    def test_unique_user_category(self, tenant, user, category):
        """Test that user-category combination is unique."""
        UserNotificationPreference.objects.create(
            tenant=tenant,
            user=user,
            category=category,
        )
        
        with pytest.raises(IntegrityError):
            UserNotificationPreference.objects.create(
                tenant=tenant,
                user=user,
                category=category,
            )
    
    def test_default_all_enabled(self, tenant, user, category):
        """Test that all channels are enabled by default."""
        pref = UserNotificationPreference.objects.create(
            tenant=tenant,
            user=user,
            category=category,
        )
        
        assert pref.sms_enabled is True
        assert pref.email_enabled is True
        assert pref.panel_enabled is True
