package options

import "strings"

type RefOption any

type TableOption struct {
	Filters []ColumnOption
	Selects []string

	// Sorting
	Sort OrderDirection

	// Pagination
	Limit  int
	Offset int

	// Ordering
	OrderBy    string
	ShouldWait bool
}

func (l TableOption) SelectString() string {
	return strings.Join(l.Selects, ",")
}

type ColumnOption struct {
	Column       string
	Value        any
	ValueNot     any
	Values       []any
	ValuesNot    []any
	Large        any
	LargeOrEqual any
	Less         any
	LessOrEqual  any
	Like         string
}

type ListOption[T RefOption] struct {
	RefOption T
	TableOption
}

func (l ListOption[T]) AddFilter(filter ColumnOption) ListOption[T] {
	l.Filters = append(l.Filters, filter)
	return l
}

func (l ListOption[T]) SetOrderBy(orderBy string) ListOption[T] {
	l.OrderBy = strings.TrimSpace(orderBy)
	return l
}

func (l ListOption[T]) SetLimit(limit int) ListOption[T] {
	l.Limit = limit
	return l
}

func (l ListOption[T]) SetOffset(offset int) ListOption[T] {
	l.Offset = offset
	return l
}

// OrderDirection specifies the direction of ordering.
type OrderDirection string

const (
	OrderAsc  OrderDirection = "ASC"
	OrderDesc OrderDirection = "DESC"
)

type TableStatement func(*TableOption)

func NewTableOption(opts ...TableStatement) TableOption {
	o := TableOption{}
	for _, opt := range opts {
		opt(&o)
	}
	return o
}

func ShouldWait() TableStatement {
	return func(o *TableOption) {
		o.ShouldWait = true
	}
}
