// repository/gallery_repository.go
package repository

import (
	"api_bb/internal/models"
	"fmt"
	"time"

	"gorm.io/gorm"
)

type GalleryRepository interface {
	Create(gallery *models.Gallery) error
	FindByID(id uint) (*models.Gallery, error)
	FindAll() ([]models.Gallery, error)
	Update(gallery *models.Gallery) error
	Delete(id uint) error
	FindByCategory(category models.GalleryCategory) ([]models.Gallery, error)
	FindByAuthor(authorID uint) ([]models.Gallery, error)
	FindPopular(limit int) ([]models.Gallery, error)
	FindRecent(limit int) ([]models.Gallery, error)
	IncrementViews(galleryID uint) error
	IncrementLikes(galleryID uint) error
	DecrementLikes(galleryID uint) error
	FindByEventDateRange(startDate, endDate time.Time) ([]models.Gallery, error)
}

type galleryRepository struct {
	db *gorm.DB
}

func NewGalleryRepository(db *gorm.DB) GalleryRepository {
	return &galleryRepository{db: db}
}

func (r *galleryRepository) Create(gallery *models.Gallery) error {
	return r.db.Create(gallery).Error
}

func (r *galleryRepository) FindByID(id uint) (*models.Gallery, error) {
	var gallery models.Gallery
	err := r.db.Preload("Author").First(&gallery, id).Error
	return &gallery, err
}

func (r *galleryRepository) FindAll() ([]models.Gallery, error) {
	var galleries []models.Gallery
	err := r.db.Preload("Author").Order("created_at DESC").Find(&galleries).Error
	return galleries, err
}

func (r *galleryRepository) Update(gallery *models.Gallery) error {
	return r.db.Save(gallery).Error
}

func (r *galleryRepository) Delete(id uint) error {
	return r.db.Delete(&models.Gallery{}, id).Error
}

func (r *galleryRepository) FindByCategory(category models.GalleryCategory) ([]models.Gallery, error) {
	var galleries []models.Gallery
	err := r.db.Preload("Author").Where("category = ?", category).Order("created_at DESC").Find(&galleries).Error
	return galleries, err
}

func (r *galleryRepository) FindByAuthor(authorID uint) ([]models.Gallery, error) {
	var galleries []models.Gallery
	err := r.db.Preload("Author").Where("author_id = ?", authorID).Order("created_at DESC").Find(&galleries).Error
	return galleries, err
}

func (r *galleryRepository) FindPopular(limit int) ([]models.Gallery, error) {
	var galleries []models.Gallery
	err := r.db.Preload("Author").Order("views DESC, likes DESC").Limit(limit).Find(&galleries).Error
	return galleries, err
}

func (r *galleryRepository) FindRecent(limit int) ([]models.Gallery, error) {
	var galleries []models.Gallery
	err := r.db.Preload("Author").Order("created_at DESC").Limit(limit).Find(&galleries).Error
	return galleries, err
}

func (r *galleryRepository) IncrementViews(galleryID uint) error {
	result := r.db.Model(&models.Gallery{}).Where("id = ?", galleryID).Update("views", gorm.Expr("views + ?", 1))
	if result.Error != nil {
		return result.Error
	}
	if result.RowsAffected == 0 {
		return fmt.Errorf("gallery not found")
	}
	return nil
}

func (r *galleryRepository) IncrementLikes(galleryID uint) error {
	result := r.db.Model(&models.Gallery{}).Where("id = ?", galleryID).Update("likes", gorm.Expr("likes + ?", 1))
	if result.Error != nil {
		return result.Error
	}
	if result.RowsAffected == 0 {
		return fmt.Errorf("gallery not found")
	}
	return nil
}

func (r *galleryRepository) DecrementLikes(galleryID uint) error {
	result := r.db.Model(&models.Gallery{}).Where("id = ? AND likes > 0", galleryID).Update("likes", gorm.Expr("likes - ?", 1))
	if result.Error != nil {
		return result.Error
	}
	if result.RowsAffected == 0 {
		return fmt.Errorf("gallery not found or likes already zero")
	}
	return nil
}

func (r *galleryRepository) FindByEventDateRange(startDate, endDate time.Time) ([]models.Gallery, error) {
	var galleries []models.Gallery
	err := r.db.Preload("Author").
		Where("event_date BETWEEN ? AND ?", startDate, endDate).
		Order("event_date DESC").
		Find(&galleries).Error
	return galleries, err
}