package repositories_astrologer

import (
	config "astrology-api/configs"
	models "astrology-api/models/astrologermodel"
	"errors"
	"strings"
	"time"

	"gorm.io/gorm"
)

type restTimeRepository struct {
	db *gorm.DB
}

func NewRestTimeRepository() RestTimeRepository {
	return &restTimeRepository{
		db: config.DB,
	}
}

func NewRestTimeRepositoryWithDB(db *gorm.DB) RestTimeRepository {
	return &restTimeRepository{
		db: db,
	}
}

func (r *restTimeRepository) GetRestTime(
	astrologerID uint,
) ([]models.AstrologerRestTime, error) {

	var restTimes []models.AstrologerRestTime

	err := r.db.
		Where("astrologer_id = ?", astrologerID).
		Where("is_delete = ?", false).
		Order("id DESC").
		Find(&restTimes).Error

	if err != nil {
		return nil, err
	}

	return restTimes, nil
}

func (r *restTimeRepository) GetRestTimeByID(
	id uint,
) (*models.AstrologerRestTime, error) {

	var restTime models.AstrologerRestTime

	err := r.db.
		Where("id = ?", id).
		Where("is_delete = ?", false).
		First(&restTime).Error

	if err != nil {

		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("rest time not found")
		}

		return nil, err
	}

	return &restTime, nil
}

func (r *restTimeRepository) CreateRestTime(
	restTime *models.AstrologerRestTime,
) error {

	if restTime == nil {
		return errors.New("rest time cannot be nil")
	}

	now := time.Now()

	restTime.IsActive = true
	restTime.IsDelete = false

	if restTime.CreatedAt == nil {
		restTime.CreatedAt = &now
	}

	if restTime.UpdatedAt == nil {
		restTime.UpdatedAt = &now
	}

	return r.db.Create(restTime).Error
}

func (r *restTimeRepository) UpdateRestTime(
	restTime *models.AstrologerRestTime,
) error {

	if restTime == nil {
		return errors.New("rest time cannot be nil")
	}

	now := time.Now()
	restTime.UpdatedAt = &now

	return r.db.
		Model(&models.AstrologerRestTime{}).
		Where("id = ?", restTime.ID).
		Updates(map[string]interface{}{
			"title":       restTime.Title,
			"rest_type":   restTime.RestType,
			"from_time":   restTime.FromTime,
			"to_time":     restTime.ToTime,
			"repeat_type": restTime.RepeatType,
			"repeat_days": restTime.RepeatDays,
			"timezone":    restTime.Timezone,
			"is_active":   restTime.IsActive,
			"is_delete":   restTime.IsDelete,
			"modified_by": restTime.ModifiedBy,
			"updated_at":  restTime.UpdatedAt,
		}).Error
}

func (r *restTimeRepository) DeleteRestTime(
	id uint,
) error {

	now := time.Now()

	return r.db.
		Model(&models.AstrologerRestTime{}).
		Where("id = ?", id).
		Updates(map[string]interface{}{
			"is_active":  false,
			"is_delete":  true,
			"updated_at": &now,
		}).Error
}

func (r *restTimeRepository) DeleteByAstrologer(
	astrologerID uint,
) error {

	now := time.Now()

	return r.db.
		Model(&models.AstrologerRestTime{}).
		Where("astrologer_id = ?", astrologerID).
		Where("is_delete = ?", false).
		Updates(map[string]interface{}{
			"is_active":  false,
			"is_delete":  true,
			"updated_at": &now,
		}).Error
}

func (r *restTimeRepository) GetActiveRestTime(
	astrologerID uint,
) ([]models.AstrologerRestTime, error) {

	var restTimes []models.AstrologerRestTime

	err := r.db.
		Where("astrologer_id = ?", astrologerID).
		Where("is_active = ?", true).
		Where("is_delete = ?", false).
		Order("from_time ASC").
		Find(&restTimes).Error

	if err != nil {
		return nil, err
	}

	return restTimes, nil
}

func (r *restTimeRepository) GetTodayRestTime(
	astrologerID uint,
) ([]models.AstrologerRestTime, error) {

	var restTimes []models.AstrologerRestTime

	today := strings.ToUpper(time.Now().Weekday().String()[:3])
	// MON, TUE, WED, THU, FRI, SAT, SUN

	err := r.db.
		Where("astrologer_id = ?", astrologerID).
		Where("is_active = ?", true).
		Where("is_delete = ?", false).
		Where(
			r.db.
				Where("repeat_type = ?", "DAILY").
				Or("repeat_days LIKE ?", "%"+today+"%"),
		).
		Order("from_time ASC").
		Find(&restTimes).Error

	if err != nil {
		return nil, err
	}

	return restTimes, nil
}

func (r *restTimeRepository) IsAstrologerOnRest(
	astrologerID uint,
) (bool, error) {

	restTimes, err := r.GetTodayRestTime(astrologerID)
	if err != nil {
		return false, err
	}

	if len(restTimes) == 0 {
		return false, nil
	}

	now := time.Now()
	currentTime := now.Format("15:04")

	for _, rest := range restTimes {

		if rest.FromTime <= currentTime &&
			currentTime <= rest.ToTime {

			return true, nil
		}
	}

	return false, nil
}

func (r *restTimeRepository) GetRestTimes(astrologerID uint) ([]models.AstrologerRestTime, error) {

	var restTimes []models.AstrologerRestTime

	err := r.db.
		Where("astrologer_id = ?", astrologerID).
		Where("is_delete = ?", false).
		Order("id DESC").
		Find(&restTimes).Error

	if err != nil {
		return nil, err
	}

	return restTimes, nil
}
