package system

import (
	"kra/pkg/database/pagination"

	"gorm.io/gorm"
)

// listRows centralizes the storage-only part shared by simple repositories:
// count the filtered query, apply the bounded page, load POs, and convert them
// at the data/biz boundary. Domain-specific filters and ordering stay in each
// repository.
type rowQueryOptions struct {
	Paginate bool
	Required bool
}

func queryRows[PO any](db *gorm.DB, page, size int, options rowQueryOptions) ([]PO, int64, error) {
	var total int64
	if err := db.Count(&total).Error; err != nil {
		return nil, 0, err
	}
	if options.Paginate {
		if options.Required {
			db = pagination.ApplyRequired(db, page, size, 100)
		} else {
			db = pagination.Apply(db, page, size, 100)
		}
	}
	var pos []PO
	if err := db.Find(&pos).Error; err != nil {
		return nil, 0, err
	}
	return pos, total, nil
}

func listRows[PO any, DO any](db *gorm.DB, page, size int, options rowQueryOptions, convert func(PO) *DO) ([]*DO, int64, error) {
	pos, total, err := queryRows[PO](db, page, size, options)
	if err != nil {
		return nil, 0, err
	}
	out := make([]*DO, 0, len(pos))
	for _, po := range pos {
		out = append(out, convert(po))
	}
	return out, total, nil
}
