from django.db import models
from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError

User = get_user_model()


class Notification(models.Model):
    """
    Notification model to store all user notifications
    """
    NOTIFICATION_TYPES = [
        ('follow', 'Follow'),
        ('follow_request', 'Follow Request'),
        ('follow_accepted', 'Follow Request Accepted'),
        ('like_post', 'Like Post'),
        ('like_comment', 'Like Comment'),
        ('comment', 'Comment'),
        ('new_post_user', 'New Post from Followed User'),
        ('new_post_category', 'New Post in Followed Category'),
    ]

    recipient = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='notifications_received'
    )
    sender = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='notifications_sent',
        null=True,
        blank=True
    )
    notification_type = models.CharField(max_length=20, choices=NOTIFICATION_TYPES)
    content = models.TextField()

    # Related objects (nullable for flexibility)
    related_post = models.ForeignKey(
        'posts.Post',
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name='notifications'
    )
    related_comment = models.ForeignKey(
        'comments.Comment',
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name='notifications'
    )
    related_category = models.ForeignKey(
        'categories.Category',
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name='notifications'
    )

    is_read = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

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

    def __str__(self):
        return f"Notification for {self.recipient.username}: {self.notification_type}"


class NotificationPreference(models.Model):
    """
    Global notification preferences for a user
    """
    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE,
        related_name='notification_preference'
    )
    notify_on_follow = models.BooleanField(default=True)
    notify_on_like = models.BooleanField(default=True)
    notify_on_comment = models.BooleanField(default=True)
    notify_on_followed_user_post = models.BooleanField(default=False)
    notify_on_followed_category_post = models.BooleanField(default=False)

    class Meta:
        verbose_name = "Notification Preference"
        verbose_name_plural = "Notification Preferences"

    def __str__(self):
        return f"Notification preferences for {self.user.username}"


class UserNotificationPreference(models.Model):
    """
    Per-user notification preference for new posts
    """
    user = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='user_notification_preferences'
    )
    target_user = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='notification_preferences_from_followers'
    )
    notify_on_new_post = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        unique_together = ('user', 'target_user')
        verbose_name = "User Notification Preference"
        verbose_name_plural = "User Notification Preferences"

    def __str__(self):
        return f"{self.user.username} -> {self.target_user.username}: {self.notify_on_new_post}"


class CategoryNotificationPreference(models.Model):
    """
    Per-category notification preference for new posts
    """
    user = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='category_notification_preferences'
    )
    category = models.ForeignKey(
        'categories.Category',
        on_delete=models.CASCADE,
        related_name='notification_preferences'
    )
    notify_on_new_post = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        unique_together = ('user', 'category')
        verbose_name = "Category Notification Preference"
        verbose_name_plural = "Category Notification Preferences"

    def __str__(self):
        return f"{self.user.username} -> {self.category.title}: {self.notify_on_new_post}"


class FollowRequest(models.Model):
    """
    Follow request model for private user accounts
    """
    STATUS_CHOICES = [
        ('pending', 'Pending'),
        ('accepted', 'Accepted'),
        ('rejected', 'Rejected'),
    ]

    requester = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='follow_requests_sent'
    )
    target = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='follow_requests_received'
    )
    status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='pending')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        unique_together = ('requester', 'target')
        verbose_name = "Follow Request"
        verbose_name_plural = "Follow Requests"
        ordering = ['-created_at']

    def __str__(self):
        return f"{self.requester.username} -> {self.target.username} ({self.status})"

    def clean(self):
        """Prevent a user from requesting to follow themselves"""
        if self.requester == self.target:
            raise ValidationError("A user cannot request to follow themselves.")

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