"""
Unit tests for core app models and base classes.
"""

import uuid
from django.test import TestCase
from django.contrib.auth import get_user_model
from django.utils import timezone

from apps.core.models import TimestampedModel, UUIDModel

User = get_user_model()


class TestModel(TimestampedModel, UUIDModel):
    """Test model for testing base model functionality."""
    
    class Meta:
        app_label = 'core'


class TimestampedModelTest(TestCase):
    """Test cases for TimestampedModel abstract base class."""
    
    def test_timestamps_auto_created(self):
        """Test that timestamps are automatically created."""
        instance = TestModel.objects.create()
        
        self.assertIsNotNone(instance.created_at)
        self.assertIsNotNone(instance.updated_at)
        self.assertEqual(instance.created_at, instance.updated_at)
    
    def test_updated_at_changes_on_save(self):
        """Test that updated_at changes when model is saved."""
        instance = TestModel.objects.create()
        original_updated_at = instance.updated_at
        
        # Small delay to ensure timestamp difference
        import time
        time.sleep(0.01)
        
        instance.save()
        
        self.assertNotEqual(instance.updated_at, original_updated_at)
        self.assertGreater(instance.updated_at, original_updated_at)
    
    def test_created_at_unchanged_on_update(self):
        """Test that created_at doesn't change on updates."""
        instance = TestModel.objects.create()
        original_created_at = instance.created_at
        
        # Small delay to ensure timestamp difference
        import time
        time.sleep(0.01)
        
        instance.save()
        
        self.assertEqual(instance.created_at, original_created_at)


class UUIDModelTest(TestCase):
    """Test cases for UUIDModel abstract base class."""
    
    def test_uuid_auto_generated(self):
        """Test that UUID is automatically generated."""
        instance = TestModel.objects.create()
        
        self.assertIsNotNone(instance.id)
        self.assertIsInstance(instance.id, uuid.UUID)
    
    def test_uuid_is_unique(self):
        """Test that UUIDs are unique."""
        instance1 = TestModel.objects.create()
        instance2 = TestModel.objects.create()
        
        self.assertNotEqual(instance1.id, instance2.id)
    
    def test_uuid_is_primary_key(self):
        """Test that UUID serves as primary key."""
        instance = TestModel.objects.create()
        
        # Should be able to retrieve by UUID
        retrieved = TestModel.objects.get(id=instance.id)
        self.assertEqual(retrieved, instance)
    
    def test_uuid_string_representation(self):
        """Test UUID string representation."""
        instance = TestModel.objects.create()
        
        # UUID should be convertible to string
        uuid_str = str(instance.id)
        self.assertIsInstance(uuid_str, str)
        self.assertEqual(len(uuid_str), 36)  # Standard UUID string length
        self.assertIn('-', uuid_str)  # Should contain hyphens


class CombinedBaseModelsTest(TestCase):
    """Test cases for models inheriting from both base classes."""
    
    def test_combined_functionality(self):
        """Test that both UUID and timestamp functionality work together."""
        instance = TestModel.objects.create()
        
        # Should have UUID
        self.assertIsNotNone(instance.id)
        self.assertIsInstance(instance.id, uuid.UUID)
        
        # Should have timestamps
        self.assertIsNotNone(instance.created_at)
        self.assertIsNotNone(instance.updated_at)
        
        # Should be retrievable by UUID
        retrieved = TestModel.objects.get(id=instance.id)
        self.assertEqual(retrieved.created_at, instance.created_at)
    
    def test_model_ordering(self):
        """Test default model ordering by created_at."""
        # Create instances with small delay
        instance1 = TestModel.objects.create()
        
        import time
        time.sleep(0.01)
        
        instance2 = TestModel.objects.create()
        
        # Should be ordered by created_at (newest first due to Meta ordering)
        instances = list(TestModel.objects.all())
        
        # Check that we have both instances
        self.assertEqual(len(instances), 2)
        
        # Verify ordering (assuming Meta ordering = ['-created_at'])
        if hasattr(TestModel._meta, 'ordering') and TestModel._meta.ordering == ['-created_at']:
            self.assertEqual(instances[0], instance2)  # Newer first
            self.assertEqual(instances[1], instance1)
        else:
            # If no specific ordering, just verify both exist
            self.assertIn(instance1, instances)
            self.assertIn(instance2, instances)
