// internal/repositories/notification_repo.go
package repositories

import (
	"errors"
	"lost-and-found/internal/models"

	"gorm.io/gorm"
)

type NotificationRepository struct {
	db *gorm.DB
}

func NewNotificationRepository(db *gorm.DB) *NotificationRepository {
	return &NotificationRepository{db: db}
}

// Create creates a new notification
func (r *NotificationRepository) Create(notification *models.Notification) error {
	return r.db.Create(notification).Error
}

// FindByID finds notification by ID
func (r *NotificationRepository) FindByID(id uint) (*models.Notification, error) {
	var notification models.Notification
	err := r.db.Preload("User").First(&notification, id).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("notification not found")
		}
		return nil, err
	}
	return &notification, nil
}

// FindByUser finds notifications for a user
func (r *NotificationRepository) FindByUser(userID uint, page, limit int, onlyUnread bool) ([]models.Notification, int64, error) {
	var notifications []models.Notification
	var total int64

	query := r.db.Model(&models.Notification{}).Where("user_id = ?", userID)

	// Filter unread if specified
	if onlyUnread {
		query = query.Where("is_read = ?", false)
	}

	// Count total
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// Get paginated results
	offset := (page - 1) * limit
	err := query.Order("created_at DESC").
		Offset(offset).Limit(limit).Find(&notifications).Error
	if err != nil {
		return nil, 0, err
	}

	return notifications, total, nil
}

// MarkAsRead marks a notification as read
func (r *NotificationRepository) MarkAsRead(id uint) error {
	notification, err := r.FindByID(id)
	if err != nil {
		return err
	}
	notification.MarkAsRead()
	return r.db.Save(notification).Error
}

// MarkAllAsRead marks all notifications for a user as read
func (r *NotificationRepository) MarkAllAsRead(userID uint) error {
	return r.db.Model(&models.Notification{}).
		Where("user_id = ? AND is_read = ?", userID, false).
		Update("is_read", true).Error
}

// Delete deletes a notification
func (r *NotificationRepository) Delete(id uint) error {
	return r.db.Delete(&models.Notification{}, id).Error
}

// DeleteAllForUser deletes all notifications for a user
func (r *NotificationRepository) DeleteAllForUser(userID uint) error {
	return r.db.Where("user_id = ?", userID).Delete(&models.Notification{}).Error
}

// CountUnread counts unread notifications for a user
func (r *NotificationRepository) CountUnread(userID uint) (int64, error) {
	var count int64
	err := r.db.Model(&models.Notification{}).
		Where("user_id = ? AND is_read = ?", userID, false).
		Count(&count).Error
	return count, err
}

// Notify creates a notification (helper method)
func (r *NotificationRepository) Notify(userID uint, notifType, title, message, entityType string, entityID *uint) error {
	return models.CreateNotification(r.db, userID, notifType, title, message, entityType, entityID)
}