package models

import (
	"fmt"
	"strings"
	"time"

	"github.com/jmoiron/sqlx"
)

// Sets - product set
type Sets struct {
	Code        string    `db:"code" cc:"code"`
	Name        string    `db:"name" cc:"name"`
	ReleaseDate time.Time `db:"release_date" cc:"release_date"`
}

// ListSetsOpts -
type ListSetsOpts struct {
	OrderBy       OrderStr
	Code          []string
	Limit, Offset int
}

// order opts
const (
	SetSearchOrderByName     OrderStr = `s."name" asc`
	SetSearchOrderByNameDesc          = `s."name" desc`
)

// CountSets -
func CountSets(arg ListSetsOpts) (c int, err error) {
	c = 0
	query := `select count(*) as count from "public"."sets" s`

	where := struct {
		Code []string `db:"code"`
	}{}
	whereStr := []string{}

	if len(arg.Code) > 0 {
		where.Code = arg.Code
		whereStr = append(whereStr, `s."code" in (:code)`)
	}

	wStr := ""
	if len(whereStr) > 0 {
		wStr = fmt.Sprintf(`where %s`, strings.Join(whereStr, " and "))
	}

	query = fmt.Sprintf("%s %s", query, wStr)

	query, args, err := sqlx.Named(query, where)
	if err != nil {
		return 0, err
	}
	query, args, err = sqlx.In(query, args)
	if err != nil {
		return 0, err
	}
	query = x.Rebind(query)

	err = x.Get(&c, query, args...)
	return
}

// ListSets -
func ListSets(arg ListSetsOpts) (sets []*Sets, err error) {
	if arg.Limit < 1 {
		arg.Limit = 1
	}
	if arg.Offset < 0 {
		arg.Offset = 0
	}
	query := `select s.code, s.name, s.release_date from "public"."sets" s`

	where := struct {
		Code []string `db:"code"`
	}{}
	whereStr := []string{}

	if len(arg.Code) > 0 {
		where.Code = arg.Code
		whereStr = append(whereStr, `s."code" in (:code)`)
	}

	wStr := ""
	if len(whereStr) > 0 {
		wStr = fmt.Sprintf("where %s", strings.Join(whereStr, " and "))
	}

	query = fmt.Sprintf("%s %s %s %s",
		query,
		wStr,
		arg.OrderBy,
		fmt.Sprintf("limit %d offset %d", arg.Limit, arg.Offset))

	query, args, err := sqlx.Named(query, where)
	if err != nil {
		return nil, err
	}
	query, args, err = sqlx.In(query, args)
	if err != nil {
		return nil, err
	}
	query = x.Rebind(query)

	err = x.Select(&sets, query, args...)
	if err != nil {
		return nil, err
	}

	return
}
