package repository

import (
	"github.com/tidbcloud/auth-server/internal/dto"
	"math"

	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

const (
	DEFAULTPAGESIZE = 100
	DEFAULTPAGE     = 1
)

func NewPaginator(page, pageSize uint32, total uint64, data interface{}) *dto.Paginator {
	totalPages := uint64(math.Ceil(float64(total) / float64(pageSize)))
	return &dto.Paginator{
		Page:       page,
		PageSize:   pageSize,
		Total:      total,
		TotalPages: totalPages,
		Data:       data,
	}
}

func Paginate[T any](db *gorm.DB, params dto.PageParams) (*dto.Paginator, error) {
	var total int64
	var offset int
	page := params.Page
	if page <= 0 {
		page = DEFAULTPAGE
	}

	pageSize := params.PageSize
	if pageSize == 0 {
		pageSize = DEFAULTPAGESIZE
	}
	offset = int((page - 1) * pageSize) // nolint

	db = applyFilters(db, params.Filters, params.AdvancedFilters)

	if params.SortBy != "" && params.Order != "" {
		db = db.Order(params.SortBy + " " + params.Order)
	}

	// count the total number of records
	var model T
	if err := db.Model(&model).Count(&total).Error; err != nil {
		return nil, err
	}

	// Create a slice to hold the results
	data := make([]T, 0)

	// Execute the query with pagination
	if err := db.Offset(offset).Limit(int(pageSize)).Find(&data).Error; err != nil {
		tilog.PlainInfo("error", zap.Error(err))
		return nil, err
	}
	paginator := NewPaginator(page, pageSize, uint64(total), data)
	return paginator, nil
}
