package query_params

import (
	"strconv"

	"git.ma-al.com/goc_daniel/b2b/app/utils/query/filters"
	"git.ma-al.com/goc_daniel/b2b/app/utils/query/find"
	"github.com/gofiber/fiber/v3"
)

var FunctionalQueryParams = []string{
	// Used to specidy order of results
	"sort",
	// Used to specify page of search resulst
	"p",
	// Used to specify number of elements on a page
	"elems",
	// Used to specify allowed values of features on products
	"values",
}

func ParseFilters[T any](c fiber.Ctx, formColumnMappimg ...map[string]string) (find.Paging, *filters.FiltersList, error) {
	// field/column based filters
	filters, err := ParseFieldFilters[T](c, formColumnMappimg...)
	if err != nil {
		return find.Paging{}, filters, err
	}
	// pagination
	pageNum, pageSize := ParsePagination(c)

	// ret
	return find.Paging{Page: pageNum, Elements: pageSize}, filters, nil
}

// Parse field related filters from params query. Produces where clauses and
// order rules.
func ParseFieldFilters[T any](c fiber.Ctx, formColumnMapping ...map[string]string) (*filters.FiltersList, error) {
	// var model T
	list := filters.NewFiltersList()
	whereScopefilters := ParseWhereScopes[T](c, []string{}, formColumnMapping...)
	list.Append(whereScopefilters...)

	ord, err := ParseOrdering[T](c, formColumnMapping...)
	if err != nil {
		return &list, err
	}
	// addDefaultOrderingIfNeeded(&ord, model)
	for i := range ord {
		if err == nil {
			list.Append(filters.Order(ord[i].Column, ord[i].IsDesc))
		}
	}

	return &list, nil
}

// TODO: Add some source of defaults for pagination size here
func ParsePagination(c fiber.Ctx) (uint, uint) {
	pageNum, _ := strconv.ParseInt(c.Query("p", "1"), 10, 64)
	pageSize, _ := strconv.ParseInt(c.Query("elems", "30"), 10, 64)
	if pageSize > 100 {
		pageSize = 100
	}
	return uint(pageNum), uint(pageSize)
}
