package repository

import (
	"context"
	"time"

	m "gitlab.com/mbugroup/lti-api.git/internal/middleware"

	"github.com/gofiber/fiber/v2"
	"gitlab.com/mbugroup/lti-api.git/internal/common/repository"
	entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
	"gorm.io/gorm"
)

type DailyChecklistRepository interface {
	repository.BaseRepository[entity.DailyChecklist]
	ListScopedChecklistIDs(c *fiber.Ctx, ids []uint) ([]uint, error)
	BulkUpdateStatus(ctx context.Context, ids []uint, status string, rejectReason *string) error
	ListByIDsWithKandang(ctx context.Context, ids []uint) ([]entity.DailyChecklist, error)
}

type DailyChecklistRepositoryImpl struct {
	*repository.BaseRepositoryImpl[entity.DailyChecklist]
}

func NewDailyChecklistRepository(db *gorm.DB) DailyChecklistRepository {
	return &DailyChecklistRepositoryImpl{
		BaseRepositoryImpl: repository.NewBaseRepository[entity.DailyChecklist](db),
	}
}

func (r *DailyChecklistRepositoryImpl) ListScopedChecklistIDs(c *fiber.Ctx, ids []uint) ([]uint, error) {
	if len(ids) == 0 {
		return []uint{}, nil
	}

	db := r.DB().WithContext(c.Context()).
		Table("daily_checklists dc").
		Select("dc.id").
		Joins("JOIN kandang_groups k ON k.id = dc.kandang_id").
		Joins("JOIN locations loc ON loc.id = k.location_id").
		Joins("JOIN areas a ON a.id = loc.area_id").
		Where("dc.id IN ?", ids).
		Where("dc.deleted_at IS NULL")

	db, err := m.ApplyLocationAreaScope(c, db, "loc.id", "a.id")
	if err != nil {
		return nil, err
	}

	var scopedIDs []uint
	if err := db.Pluck("dc.id", &scopedIDs).Error; err != nil {
		return nil, err
	}

	return scopedIDs, nil
}

func (r *DailyChecklistRepositoryImpl) BulkUpdateStatus(ctx context.Context, ids []uint, status string, rejectReason *string) error {
	if len(ids) == 0 {
		return nil
	}

	updateBody := map[string]any{
		"status":        status,
		"reject_reason": rejectReason,
		"updated_at":    time.Now(),
	}

	return r.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		result := tx.Model(&entity.DailyChecklist{}).
			Where("id IN ?", ids).
			Updates(updateBody)
		if result.Error != nil {
			return result.Error
		}
		if result.RowsAffected != int64(len(ids)) {
			return gorm.ErrRecordNotFound
		}
		return nil
	})
}

func (r *DailyChecklistRepositoryImpl) ListByIDsWithKandang(ctx context.Context, ids []uint) ([]entity.DailyChecklist, error) {
	if len(ids) == 0 {
		return []entity.DailyChecklist{}, nil
	}

	var items []entity.DailyChecklist
	if err := r.DB().WithContext(ctx).
		Where("id IN ?", ids).
		Preload("Kandang").
		Find(&items).Error; err != nil {
		return nil, err
	}

	return items, nil
}
