package repositoryimpl

import (
	"center-api/internal/biz/bo"
	"center-api/internal/pkg/mapstructure"
	"context"
)

type Query[Q any] interface {
	Limit(limit int) *Q
	Offset(offset int) *Q
	CountX(ctx context.Context) int
	Clone() *Q
}

// Base 基础类型，提供了 po与do之间的转换等共用方法，在do中嵌入此类型创建，大部分情况下可不用再重复写 ToEntity 和 ToEntities 方法
type Base[P, D, Q any] struct {
}

// ToEntity 转换成实体
// 支持基本类型的值对象
// 支持 edge 的实体转换，注意名称要保持一致，否则只能在组合类覆盖此此方法
func (b *Base[P, D, Q]) ToEntity(p *P) *D {
	if p == nil {
		return nil
	}
	var d *D
	_ = mapstructure.Decode(p, &d)
	return d
}

// ToEntities 转换成实体
// 支持基本类型的值对象
// 支持 edge 的实体转换，注意名称要保持一致，否则只能在组合类覆盖此此方法
func (b *Base[P, D, Q]) ToEntities(ps []*P) []*D {
	if ps == nil {
		return nil
	}
	var entities []*D
	//e := b.MapstructureDeepDecode(ps, &entities)
	_ = mapstructure.Decode(ps, &entities)
	return entities
}

// SetPageByBo 设置分页
func (b *Base[P, D, Q]) SetPageByBo(query Query[Q], pageBo *bo.ReqPageBo) {
	if query == nil || pageBo == nil {
		return
	}
	if pageBo.Limit > 0 {
		query.Limit(pageBo.Limit)
	}
	if pageBo.Page > 0 {
		query.Offset(pageBo.GetOffset())
	}
}

// QueryRespPage 获取分页数据
func (b *Base[P, D, Q]) QueryRespPage(ctx context.Context, query Query[Q], pageBo *bo.ReqPageBo) *bo.RespPageBo {
	cloneQ := ((any)(query.Clone())).(Query[Q])
	cloneQ.Offset(0)
	cloneQ.Limit(0)
	//查询总数
	total := cloneQ.CountX(ctx)
	resp := &bo.RespPageBo{Total: total}
	if pageBo != nil {
		resp.Page = pageBo.Page
		resp.Limit = pageBo.Limit
	}
	return resp
}
