from django.db import models
from django.utils.translation import gettext_lazy as _
from django.utils import timezone


class NotificationType(models.TextChoices):
    BOOKING_REMINDER = 'booking_reminder', _('Booking Reminder')
    BOOKING_CONFIRMED = 'booking_confirmed', _('Booking Confirmed')
    BOOKING_CANCELLED = 'booking_cancelled', _('Booking Cancelled')
    OFFER_NEW = 'offer_new', _('New Offer')
    REVIEW_NEW = 'review_new', _('New Review')
    REVIEW_RESPONSE = 'review_response', _('Review Response')
    PLACE_UPDATE = 'place_update', _('Place Update')
    GENERAL = 'general', _('General')


class Notification(models.Model):
    """Notification Model"""
    user = models.ForeignKey(
        'accounts.User',
        on_delete=models.CASCADE,
        related_name='notifications',
        verbose_name=_('User')
    )
    type = models.CharField(
        max_length=50,
        choices=NotificationType.choices,
        default=NotificationType.GENERAL,
        verbose_name=_('Type')
    )
    title = models.CharField(max_length=200, verbose_name=_('Title'))
    message = models.TextField(verbose_name=_('Message'))
    data = models.JSONField(default=dict, blank=True, verbose_name=_('Data'))
    is_read = models.BooleanField(default=False, verbose_name=_('Is Read'))
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name = _('Notification')
        verbose_name_plural = _('Notifications')
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['user', 'is_read']),
            models.Index(fields=['type']),
        ]

    def __str__(self):
        return f'{self.user.username} - {self.title}'

    def mark_as_read(self):
        """Mark notification as read"""
        self.is_read = True
        self.save(update_fields=['is_read'])


class Favorite(models.Model):
    """Favorite Model - User's favorite places"""
    user = models.ForeignKey(
        'accounts.User',
        on_delete=models.CASCADE,
        related_name='favorites',
        verbose_name=_('User')
    )
    place = models.ForeignKey(
        'places.Place',
        on_delete=models.CASCADE,
        related_name='favorited_by',
        verbose_name=_('Place')
    )
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name = _('Favorite')
        verbose_name_plural = _('Favorites')
        unique_together = ['user', 'place']
        indexes = [
            models.Index(fields=['user']),
            models.Index(fields=['place']),
        ]

    def __str__(self):
        return f'{self.user.username} - {self.place.name}'


class Activity(models.Model):
    """Activity Model - User activity history"""
    class ActivityType(models.TextChoices):
        BOOKING = 'booking', _('Booking')
        VISIT = 'visit', _('Visit')
        SEARCH = 'search', _('Search')
        FAVORITE = 'favorite', _('Favorite')
        REVIEW = 'review', _('Review')

    user = models.ForeignKey(
        'accounts.User',
        on_delete=models.CASCADE,
        related_name='activities',
        verbose_name=_('User')
    )
    type = models.CharField(
        max_length=20,
        choices=ActivityType.choices,
        verbose_name=_('Type')
    )
    place = models.ForeignKey(
        'places.Place',
        on_delete=models.CASCADE,
        blank=True,
        null=True,
        related_name='activities',
        verbose_name=_('Place')
    )
    description = models.TextField(blank=True, null=True, verbose_name=_('Description'))
    metadata = models.JSONField(default=dict, blank=True, verbose_name=_('Metadata'))
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name = _('Activity')
        verbose_name_plural = _('Activities')
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['user', 'type']),
            models.Index(fields=['place']),
        ]

    def __str__(self):
        return f'{self.user.username} - {self.type}'


class ReportType(models.TextChoices):
    """Report Type Choices"""
    INAPPROPRIATE_PLACE = 'inappropriate_place', _('Inappropriate Place')
    ABUSIVE_REVIEW = 'abusive_review', _('Abusive Review')
    VIOLATING_CONTENT = 'violating_content', _('Violating Content')
    SPAM = 'spam', _('Spam')
    FAKE = 'fake', _('Fake')
    OTHER = 'other', _('Other')


class ReportStatus(models.TextChoices):
    """Report Status Choices"""
    PENDING = 'pending', _('Pending')
    UNDER_REVIEW = 'under_review', _('Under Review')
    RESOLVED = 'resolved', _('Resolved')
    REJECTED = 'rejected', _('Rejected')
    DISMISSED = 'dismissed', _('Dismissed')


class Report(models.Model):
    """Report Model - For reporting inappropriate content"""
    reporter = models.ForeignKey(
        'accounts.User',
        on_delete=models.CASCADE,
        related_name='reports_made',
        verbose_name=_('Reporter')
    )
    report_type = models.CharField(
        max_length=50,
        choices=ReportType.choices,
        verbose_name=_('Report Type')
    )
    status = models.CharField(
        max_length=20,
        choices=ReportStatus.choices,
        default=ReportStatus.PENDING,
        verbose_name=_('Status')
    )
    
    # Content being reported (Generic Foreign Key approach)
    place = models.ForeignKey(
        'places.Place',
        on_delete=models.CASCADE,
        related_name='reports',
        blank=True,
        null=True,
        verbose_name=_('Place')
    )
    review = models.ForeignKey(
        'reviews.Review',
        on_delete=models.CASCADE,
        related_name='reports',
        blank=True,
        null=True,
        verbose_name=_('Review')
    )
    
    reason = models.TextField(verbose_name=_('Reason'))
    description = models.TextField(blank=True, null=True, verbose_name=_('Description'))
    evidence = models.JSONField(default=list, blank=True, verbose_name=_('Evidence'))  # URLs to screenshots, etc.
    
    # Admin fields
    admin_notes = models.TextField(blank=True, null=True, verbose_name=_('Admin Notes'))
    resolved_by = models.ForeignKey(
        'accounts.User',
        on_delete=models.SET_NULL,
        related_name='reports_resolved',
        blank=True,
        null=True,
        verbose_name=_('Resolved By')
    )
    resolved_at = models.DateTimeField(blank=True, null=True, verbose_name=_('Resolved At'))
    
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = _('Report')
        verbose_name_plural = _('Reports')
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['reporter']),
            models.Index(fields=['report_type']),
            models.Index(fields=['status']),
            models.Index(fields=['place']),
            models.Index(fields=['review']),
            models.Index(fields=['status', 'created_at']),
        ]

    def __str__(self):
        content = self.place.name if self.place else (self.review.place.name if self.review else 'Unknown')
        return f'{self.reporter.username} - {self.get_report_type_display()} - {content}'

    def clean(self):
        """Validate that either place or review is set"""
        from django.core.exceptions import ValidationError
        if not self.place and not self.review:
            raise ValidationError(_('Either place or review must be set'))
        if self.place and self.review:
            raise ValidationError(_('Cannot report both place and review in the same report'))

    def save(self, *args, **kwargs):
        self.full_clean()
        super().save(*args, **kwargs)

    def mark_as_resolved(self, admin_user, notes=None):
        """Mark report as resolved"""
        self.status = ReportStatus.RESOLVED
        self.resolved_by = admin_user
        self.resolved_at = timezone.now()
        if notes:
            self.admin_notes = notes
        self.save(update_fields=['status', 'resolved_by', 'resolved_at', 'admin_notes'])

    def mark_as_rejected(self, admin_user, notes=None):
        """Mark report as rejected"""
        self.status = ReportStatus.REJECTED
        self.resolved_by = admin_user
        self.resolved_at = timezone.now()
        if notes:
            self.admin_notes = notes
        self.save(update_fields=['status', 'resolved_by', 'resolved_at', 'admin_notes'])
