from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.conf import settings
from django.utils import timezone
from django.apps import apps

class EditSubmission(models.Model):
    STATUS_CHOICES = [
        ('PENDING', 'Pending'),
        ('APPROVED', 'Approved'),
        ('REJECTED', 'Rejected'),
        ('AUTO_APPROVED', 'Auto Approved'),
    ]

    SUBMISSION_TYPE_CHOICES = [
        ('EDIT', 'Edit Existing'),
        ('CREATE', 'Create New'),
    ]

    # Who submitted the edit
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='edit_submissions'
    )

    # What is being edited (Park or Ride)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField(null=True, blank=True)  # Null for new objects
    content_object = GenericForeignKey('content_type', 'object_id')

    # Type of submission
    submission_type = models.CharField(
        max_length=10,
        choices=SUBMISSION_TYPE_CHOICES,
        default='EDIT'
    )

    # The actual changes/data
    changes = models.JSONField(
        help_text='JSON representation of the changes or new object data'
    )
    
    # Metadata
    reason = models.TextField(
        help_text='Why this edit/addition is needed'
    )
    source = models.TextField(
        blank=True,
        help_text='Source of information (if applicable)'
    )
    status = models.CharField(
        max_length=20,
        choices=STATUS_CHOICES,
        default='PENDING'
    )
    submitted_at = models.DateTimeField(auto_now_add=True)
    
    # Review details
    reviewed_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='reviewed_submissions'
    )
    reviewed_at = models.DateTimeField(null=True, blank=True)
    review_notes = models.TextField(
        blank=True,
        help_text='Notes from the moderator about this submission'
    )

    class Meta:
        ordering = ['-submitted_at']
        indexes = [
            models.Index(fields=['content_type', 'object_id']),
            models.Index(fields=['status']),
        ]

    def __str__(self):
        action = "creation" if self.submission_type == 'CREATE' else "edit"
        target = self.content_object or self.content_type.model_class().__name__
        return f"{action} by {self.user.username} on {target}"

    def _resolve_foreign_keys(self, data):
        """Convert foreign key IDs to model instances"""
        model_class = self.content_type.model_class()
        resolved_data = data.copy()

        for field_name, value in data.items():
            field = model_class._meta.get_field(field_name)
            if isinstance(field, models.ForeignKey) and value is not None:
                related_model = field.related_model
                resolved_data[field_name] = related_model.objects.get(id=value)

        return resolved_data

    def approve(self, moderator, notes=''):
        """Approve the submission and apply the changes"""
        self.status = 'APPROVED'
        self.reviewed_by = moderator
        self.reviewed_at = timezone.now()
        self.review_notes = notes
        
        model_class = self.content_type.model_class()
        resolved_data = self._resolve_foreign_keys(self.changes)

        if self.submission_type == 'CREATE':
            # Create new object
            obj = model_class(**resolved_data)
            obj.save()
            # Update object_id after creation
            self.object_id = obj.id
        else:
            # Apply changes to existing object
            obj = self.content_object
            for field, value in resolved_data.items():
                setattr(obj, field, value)
            obj.save()
        
        self.save()
        return obj

    def reject(self, moderator, notes):
        """Reject the submission"""
        self.status = 'REJECTED'
        self.reviewed_by = moderator
        self.reviewed_at = timezone.now()
        self.review_notes = notes
        self.save()

    def auto_approve(self):
        """Auto-approve the submission (for moderators/admins)"""
        self.status = 'AUTO_APPROVED'
        self.reviewed_by = self.user
        self.reviewed_at = timezone.now()
        
        model_class = self.content_type.model_class()
        resolved_data = self._resolve_foreign_keys(self.changes)

        if self.submission_type == 'CREATE':
            # Create new object
            obj = model_class(**resolved_data)
            obj.save()
            # Update object_id after creation
            self.object_id = obj.id
        else:
            # Apply changes to existing object
            obj = self.content_object
            for field, value in resolved_data.items():
                setattr(obj, field, value)
            obj.save()
        
        self.save()
        return obj

class PhotoSubmission(models.Model):
    STATUS_CHOICES = [
        ('PENDING', 'Pending'),
        ('APPROVED', 'Approved'),
        ('REJECTED', 'Rejected'),
        ('AUTO_APPROVED', 'Auto Approved'),
    ]

    # Who submitted the photo
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='photo_submissions'
    )

    # What the photo is for (Park or Ride)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    # The photo itself
    photo = models.ImageField(upload_to='submissions/photos/')
    caption = models.CharField(max_length=255, blank=True)
    date_taken = models.DateField(null=True, blank=True)
    
    # Metadata
    status = models.CharField(
        max_length=20,
        choices=STATUS_CHOICES,
        default='PENDING'
    )
    submitted_at = models.DateTimeField(auto_now_add=True)
    
    # Review details
    reviewed_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='reviewed_photos'
    )
    reviewed_at = models.DateTimeField(null=True, blank=True)
    review_notes = models.TextField(
        blank=True,
        help_text='Notes from the moderator about this photo submission'
    )

    class Meta:
        ordering = ['-submitted_at']
        indexes = [
            models.Index(fields=['content_type', 'object_id']),
            models.Index(fields=['status']),
        ]

    def __str__(self):
        return f"Photo submission by {self.user.username} for {self.content_object}"

    def approve(self, moderator, notes=''):
        """Approve the photo submission"""
        from media.models import Photo
        
        self.status = 'APPROVED'
        self.reviewed_by = moderator
        self.reviewed_at = timezone.now()
        self.review_notes = notes
        
        # Create the approved photo
        Photo.objects.create(
            user=self.user,
            content_type=self.content_type,
            object_id=self.object_id,
            image=self.photo,
            caption=self.caption,
            date_taken=self.date_taken
        )
        
        self.save()

    def reject(self, moderator, notes):
        """Reject the photo submission"""
        self.status = 'REJECTED'
        self.reviewed_by = moderator
        self.reviewed_at = timezone.now()
        self.review_notes = notes
        self.save()

    def auto_approve(self):
        """Auto-approve the photo submission (for moderators/admins)"""
        from media.models import Photo
        
        self.status = 'AUTO_APPROVED'
        self.reviewed_by = self.user
        self.reviewed_at = timezone.now()
        
        # Create the approved photo
        Photo.objects.create(
            user=self.user,
            content_type=self.content_type,
            object_id=self.object_id,
            image=self.photo,
            caption=self.caption,
            date_taken=self.date_taken
        )
        
        self.save()
