package service

import (
	"context"
	"github.com/prometheus/common/log"
	"github.com/tidwall/gjson"
	"gopkg.in/olivere/elastic.v5"
	"regexp"
	"search_server/pkg/common"
	"search_server/pkg/config"
	"search_server/pkg/es"
	"search_server/protopb/bom"
	"strings"
)

type BomServiceImpl struct{}

func (bs *BomServiceImpl) AutoSpu(ctx context.Context, req *bom.AutoSpuRequest, rsp *bom.AutoSpuResponse) error {
	goodsNameSlice := AutoSpu(req.GoodsName)
	if len(goodsNameSlice) == 0 {
		rsp.ErrorCode = 1
	}
	rsp.Data = goodsNameSlice
	return nil
}

func (bs *BomServiceImpl) Recommend(ctx context.Context, req *bom.RecommendRequest, rsp *bom.RecommendResponse) error {
	if req.Flag == 0 {
		rsp.ErrorCode = 101
		rsp.ErrorMessage = "参数不全"
		return nil
	}
	rsp.Data = Recommend(req)
	return nil
}

func NewBomServiceImpl() *BomServiceImpl {
	return &BomServiceImpl{}
}

//构建请求参数
func AutoSpu(goodsName string) []string {
	replace, _ := regexp.Compile("[^A-Za-z0-9]+")
	goodsName = replace.ReplaceAllString(goodsName, "")
	goodsName = strings.ToUpper(goodsName)

	query := getTermQuery(goodsName)
	source := elastic.NewSearchSource().Query(query)
	source = source.From(0).Size(10)
	searchRequestStr, _ := elastic.NewSearchRequest().Source(source).Body()
	result, err := es.CurlES("lie_spu", searchRequestStr)
	//只要其中的goods_name
	if err != nil {
		log.Error(err)
	}
	goodsNameList := make([]string, 0)
	goodsList := gjson.Get(result, "hits.hits.#._source").Array()
	for _, goods := range goodsList {
		goodsName := gjson.Get(goods.String(), "auto_goods_name").String()
		goodsNameList = append(goodsNameList, goodsName)
	}
	return goodsNameList
}

//构建term条件
func getTermQuery(goodsName string) (query *elastic.BoolQuery) {
	query = elastic.NewBoolQuery()
	query.Filter(elastic.NewTermQuery("auto_goods_name", goodsName))
	if config.Get("web.mode").String() != "debug" {
		query.Filter(elastic.NewTermQuery("status", 1))
	}
	query.MustNot(elastic.NewTermQuery("brand_id", 0))
	return query
}

//推荐商品搜索
func Recommend(req *bom.RecommendRequest) (rsp *bom.ResponseData) {
	var err error
	//先去请求参数,看是否是参数,如果是参数的话,需要修改请求的商品名称
	var goodsName string
	if req.GoodsName != "" {
		goodsName, err = SearchAttr(req.GoodsName, req.Encap)
	}
	//如果没有型号,但是有参数(参数有可能是型号),那就去匹配参数
	if req.GoodsName == "" && req.Attrs != "" {
		goodsName, err = SearchAttr(req.Attrs, req.Encap)
	}
	if goodsName != "" {
		req.GoodsName = goodsName
	}
	//转换请求参数
	req = changeRecommendReq(req)
	//获取需要请求的索引
	index := getRecommendSearchIndex(req)
	//获取es的请求参数
	queryJson := getRecommendSearchParams(false, req)
	result, err := es.CurlES(index, queryJson)
	if err != nil {
		log.Error(err)
	}
	//获取需要的数据
	total := gjson.Get(result, "hits.total").Int()
	var response bom.ResponseData
	response.Total = total
	//获取goods_id列表去商品服务获取商品
	list := gjson.Get(result, "hits.hits.#._source").Array()
	var goodsIdList []string
	var goodsIdListStr string
	for _, goods := range list {
		goodsId := gjson.Get(goods.String(), "goods_id").String()
		goodsIdList = append(goodsIdList, goodsId)
	}
	goodsIdListStr = strings.Join(goodsIdList, ",")
	goodsList, err := GetGoodsInfo(goodsIdListStr)
	response.Data = goodsList
	response.Flag = req.Flag
	return &response
}

//处理recommend接口的请求参数
func changeRecommendReq(req *bom.RecommendRequest) (res *bom.RecommendRequest) {
	//设置默认值
	if req.Num == 0 {
		req.Num = 1
	}
	//转换处理商品名称
	replace, _ := regexp.Compile("[^A-Za-z0-9]+")
	req.GoodsName = replace.ReplaceAllString(req.GoodsName, "")
	req.GoodsName = strings.ToUpper(req.GoodsName)

	if req.Flag == 2 {
		//截取字符后再精确匹配
		req.GoodsName = common.SubKeyWordStr(req.GoodsName)
	}
	return req
}

//获取recommend接口需要请求的索引
func getRecommendSearchIndex(req *bom.RecommendRequest) (index string) {
	index = config.Get("es.hk_delivery_type_supplier").String()
	//如果是内地收货的情况下
	if req.DeliveryType == 1 {
		index = index + ",liexin_ziying,zhuanmai"
	}
	return
}

//获取请求es的参数
func getRecommendSearchParams(isRawSearch bool, req *bom.RecommendRequest) (result string) {
	result = getBomTermQuery(req.GoodsName, "", req.Num, isRawSearch)
	return
}

//获取bom单的term查询
func getBomTermQuery(goodsName, brandName string, number int32, isRawSearch bool) (result string) {
	query := elastic.NewBoolQuery()
	if isRawSearch {
		field := "auto_goods_name.raw"
		replace, _ := regexp.Compile("[^A-Za-z0-9]+")
		goodsName := replace.ReplaceAllString(goodsName, "")
		goodsName = strings.ToUpper(goodsName)
		//搜索商品名称
		query = query.Filter(elastic.NewTermQuery(field, goodsName))
		//判断是否存在brandName,存在就去搜索brandName
		if brandName != "" {
			brandName = strings.ToUpper(brandName)
			query = query.Should(elastic.NewConstantScoreQuery(elastic.NewTermQuery("brand_name", brandName)).Boost(2))
		}
		//搜索库存
		query = query.Should(elastic.NewConstantScoreQuery(elastic.NewRangeQuery("stock").Gte(number)))
	} else {
		field := "auto_goods_name"
		query = query.Must(elastic.NewTermQuery(field, goodsName))
	}
	if config.Get("web.mode").String() != "debug" {
		query.Filter(elastic.NewTermQuery("status", 1))
	}
	source := elastic.NewSearchSource().Query(query)
	source.From(0)
	if isRawSearch {
		source.Size(100)
	} else {
		source.Size(1)
	}
	source.Sort("_score", false).Sort("sort", false).Sort("single_price", true)
	queryRequest := elastic.NewSearchRequest().Source(source)
	result, _ = queryRequest.Body()
	return result
}