// repository/event_registration_repository.go
package repository

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

	"gorm.io/gorm"
)

type EventRegistrationRepository interface {
	Create(registration *models.EventRegistration) error
	FindByID(id uint) (*models.EventRegistration, error)
	FindByEventID(eventID uint) ([]models.EventRegistration, error)
	FindByUserID(userID uint) ([]models.EventRegistration, error)
	FindByEventAndUser(eventID, userID uint) (*models.EventRegistration, error)
	Update(registration *models.EventRegistration) error
	Delete(id uint) error
	UpdateStatus(registrationID uint, status string) error
	UpdateResultTime(registrationID uint, resultTime string) error
	CountByEventID(eventID uint) (int64, error)
}

type eventRegistrationRepository struct {
	db *gorm.DB
}

func NewEventRegistrationRepository(db *gorm.DB) EventRegistrationRepository {
	return &eventRegistrationRepository{db: db}
}

func (r *eventRegistrationRepository) Create(registration *models.EventRegistration) error {
	return r.db.Create(registration).Error
}

func (r *eventRegistrationRepository) FindByID(id uint) (*models.EventRegistration, error) {
	var registration models.EventRegistration
	err := r.db.Preload("Event").Preload("User").First(&registration, id).Error
	return &registration, err
}

func (r *eventRegistrationRepository) FindByEventID(eventID uint) ([]models.EventRegistration, error) {
	var registrations []models.EventRegistration
	err := r.db.Preload("User").Where("event_id = ?", eventID).Find(&registrations).Error
	return registrations, err
}

func (r *eventRegistrationRepository) FindByUserID(userID uint) ([]models.EventRegistration, error) {
	var registrations []models.EventRegistration
	err := r.db.Preload("Event").Where("user_id = ?", userID).Find(&registrations).Error
	return registrations, err
}

func (r *eventRegistrationRepository) FindByEventAndUser(eventID, userID uint) (*models.EventRegistration, error) {
	var registration models.EventRegistration
	err := r.db.Where("event_id = ? AND user_id = ?", eventID, userID).First(&registration).Error
	return &registration, err
}

func (r *eventRegistrationRepository) Update(registration *models.EventRegistration) error {
	return r.db.Save(registration).Error
}

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

func (r *eventRegistrationRepository) UpdateStatus(registrationID uint, status string) error {
	result := r.db.Model(&models.EventRegistration{}).Where("id = ?", registrationID).Update("status", status)
	if result.Error != nil {
		return result.Error
	}
	if result.RowsAffected == 0 {
		return fmt.Errorf("registration not found")
	}
	return nil
}

func (r *eventRegistrationRepository) UpdateResultTime(registrationID uint, resultTime string) error {
	result := r.db.Model(&models.EventRegistration{}).Where("id = ?", registrationID).Update("result_time", resultTime)
	if result.Error != nil {
		return result.Error
	}
	if result.RowsAffected == 0 {
		return fmt.Errorf("registration not found")
	}
	return nil
}

func (r *eventRegistrationRepository) CountByEventID(eventID uint) (int64, error) {
	var count int64
	err := r.db.Model(&models.EventRegistration{}).Where("event_id = ? AND status IN ?", eventID, []string{"pending", "confirmed"}).Count(&count).Error
	return count, err
}