package tool

import (
	"context"
	"errors"
	"github.com/syyongx/php2go"
	"math"
	"reflect"
)

func NewPaginator(queryBuild any, page, pageSize int, ctx2 ...context.Context) (*Paginate, error) {
	ctx := context.TODO()
	if len(ctx2) > 0 {
		ctx = ctx2[0]
	}

	obj := reflect.ValueOf(queryBuild)

	var structMethods []string
	t := obj.Type()
	for i := 0; i < t.NumMethod(); i++ {
		structMethods = append(structMethods, t.Method(i).Name)
	}

	for _, v := range []string{"Limit", "Offset", "All", "Count"} {
		if !php2go.InArray(v, structMethods) {
			return nil, errors.New("方法不存在:" + v)
		}
	}
	data := make([]any, 1)
	total := 0
	offset := (page - 1) * pageSize
	obj.MethodByName("Limit").Call([]reflect.Value{reflect.ValueOf(pageSize)})
	obj.MethodByName("Offset").Call([]reflect.Value{reflect.ValueOf(offset)})
	vals := obj.MethodByName("All").Call([]reflect.Value{reflect.ValueOf(ctx)})
	for _, v := range vals {
		data = append(data, v.Interface())
	}
	valsCnt := obj.MethodByName("Count").Call([]reflect.Value{reflect.ValueOf(ctx)})
	for _, v := range valsCnt {
		t, ok := v.Interface().(int)
		if ok {
			total = t
		}
	}

	lastPage := math.Ceil(float64(total / pageSize))
	return &Paginate{
		Page:     page,
		PageSize: pageSize,
		Total:    total,
		LastPage: int(lastPage),
		Data:     data,
	}, nil
}
