package repository

import (
	"context"
	"time"

	"gitlab.com/mbugroup/lti-api.git/internal/common/repository"
	entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
	validation "gitlab.com/mbugroup/lti-api.git/internal/modules/production/uniformities/validations"
	"gorm.io/gorm"
)

type UniformityRepository interface {
	repository.BaseRepository[entity.ProjectFlockKandangUniformity]
	GetAllWithFilters(ctx context.Context, offset, limit int, params *validation.Query, modifiers ...func(*gorm.DB) *gorm.DB) ([]entity.ProjectFlockKandangUniformity, int64, error)
	WithDefaultRelations() func(*gorm.DB) *gorm.DB
	DeleteByProjectFlockKandangIDs(ctx context.Context, projectFlockKandangIDs []uint) error
}

type UniformityRepositoryImpl struct {
	*repository.BaseRepositoryImpl[entity.ProjectFlockKandangUniformity]
}

func NewUniformityRepository(db *gorm.DB) UniformityRepository {
	return &UniformityRepositoryImpl{
		BaseRepositoryImpl: repository.NewBaseRepository[entity.ProjectFlockKandangUniformity](db),
	}
}

func (r *UniformityRepositoryImpl) GetAllWithFilters(ctx context.Context, offset, limit int, params *validation.Query, modifiers ...func(*gorm.DB) *gorm.DB) ([]entity.ProjectFlockKandangUniformity, int64, error) {
	return r.GetAll(ctx, offset, limit, func(db *gorm.DB) *gorm.DB {
		db = r.applyQueryFilters(r.WithDefaultRelations()(db), params)
		for _, modifier := range modifiers {
			if modifier != nil {
				db = modifier(db)
			}
		}
		return db
	})
}

func (r *UniformityRepositoryImpl) WithDefaultRelations() func(*gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		return db.
			Preload("ProjectFlockKandang.ProjectFlock").
			Preload("ProjectFlockKandang.ProjectFlock.Location").
			Preload("ProjectFlockKandang.Chickins").
			Preload("ProjectFlockKandang.Kandang.Location")
	}
}

func (r *UniformityRepositoryImpl) applyQueryFilters(db *gorm.DB, params *validation.Query) *gorm.DB {
	if params == nil {
		return db
	}

	if params.ProjectFlockKandangId != 0 {
		db = db.Where("project_flock_kandang_id = ?", params.ProjectFlockKandangId)
	}
	if params.Week != 0 {
		db = db.Where("week = ?", params.Week)
	}

	startDateValue, endDateValue, err := validation.ParseDateRange(params.StartDate, params.EndDate)
	if err == nil {
		if startDateValue != nil && endDateValue != nil {
			db = db.Where("uniform_date >= ? AND uniform_date < ?", *startDateValue, endDateValue.Add(24*time.Hour))
		} else if startDateValue != nil {
			db = db.Where("uniform_date >= ?", *startDateValue)
		} else if endDateValue != nil {
			db = db.Where("uniform_date < ?", endDateValue.Add(24*time.Hour))
		}
	}

	return db.Order("uniform_date DESC").Order("id DESC")
}

func (r *UniformityRepositoryImpl) DeleteByProjectFlockKandangIDs(ctx context.Context, projectFlockKandangIDs []uint) error {
	if len(projectFlockKandangIDs) == 0 {
		return nil
	}
	return r.DB().WithContext(ctx).
		Unscoped().
		Where("project_flock_kandang_id IN ?", projectFlockKandangIDs).
		Delete(&entity.ProjectFlockKandangUniformity{}).Error
}
