package rank

import (
	"fmt"

	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/algorithm"
	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/algorithm/eas"
	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/context"
	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/log"
	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/module"
	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/recconf"
)

type ColdStartRank struct {
	RecallName string
	AlgoName   string
}

func NewColdStartRank(recallName, algoName string) *ColdStartRank {

	return &ColdStartRank{
		RecallName: recallName,
		AlgoName:   algoName,
	}
}
func (r *ColdStartRank) Filter(User *module.User, item *module.Item, context *context.RecommendContext) bool {
	if item.GetRecallName() == r.RecallName {
		return true
	}
	return false
}

func (r *ColdStartRank) Rank(user *module.User, items []*module.Item, requestData []map[string]interface{}, context *context.RecommendContext) {
	// if algo name not set, no need rank
	if r.AlgoName == "" {
		return
	}
	if len(items) == 0 {
		return
	}
	var itemIds []string
	for _, item := range items {
		itemIds = append(itemIds, string(item.Id))
	}

	limit := context.Size / 10
	if limit < 1 {
		limit = 1
	}

	request := eas.LincubRequestData{
		RequestId:   context.RecommendId,
		Scene:       context.GetParameter("scene").(string),
		UserId:      string(user.Id),
		UserFeature: user.MakeUserFeatures2(),
		Items:       itemIds,
		Limit:       limit,
	}

	ret, err := algorithm.Run(r.AlgoName, &request)
	if err != nil {
		log.Error(fmt.Sprintf("requestId=%s\tevent=ColdStartRank\terr=%v", context.RecommendId, err))
		return
	}

	results, err := eas.LinucbResponseFunc(ret)
	if err != nil {
		log.Error(fmt.Sprintf("requestId=%s\tevent=ColdStartRank\terr=%v", context.RecommendId, err))
		return
	}

	for _, linucbItem := range results {
		for _, item := range items {
			if linucbItem.ItemId == string(item.Id) {
				item.Score = linucbItem.GetScore()
			}
		}
	}

}

func LoadColdStartRankConfig(config *recconf.RecommendConfig) {
	for scene, conf := range config.ColdStartRankConfs {
		rank := NewColdStartRank(conf.RecallName, conf.AlgoName)

		RegisterRank(scene, rank)
	}
}
