package logic

import (
	"app.yhyue.com/moapp/jybase/common"
	"bytes"
	"context"
	"crypto/md5"
	"fmt"
	IC "jyBXBase/rpc/init"
	"jyBXBase/rpc/util"
	"log"
	"net/url"
	"sort"
	"strings"

	"jyBXBase/rpc/bxbase"
	"jyBXBase/rpc/internal/svc"

	"github.com/zeromicro/go-zero/core/logx"
)

type CheckSearchLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewCheckSearchLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CheckSearchLogic {
	return &CheckSearchLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

// 校验搜索列表
func (l *CheckSearchLogic) CheckSearch(in *bxbase.AddSearchReq) (res *bxbase.CheckRes, err error) {
	res = new(bxbase.CheckRes)
	if in.UserId == "" {
		res.ErrCode = 1
		res.ErrMsg = "用户未登录"
		return
	}
	if in.Keywords == "" && in.AdditionalWords == "" && in.Industry == "" {
		res.ErrCode = 1
		res.ErrMsg = "请先输入关键词或选择行业"
		return
	}
	log.Println("校验搜索列表:", in)
	in.Keywords = strings.Replace(in.Keywords, " ", ",", -1)
	query := map[string]interface{}{
		"user_id": in.UserId,
	}
	if IC.Mgo.Count("search_condition", query) >= 10 {
		res.ErrCode = 1
		res.ErrMsg = "对不起，最多可保存10个筛选条件。"
		return
	}
	in.Keywords = ValueSort(in.Keywords)
	in.Area = ValueSort(in.Area)
	in.City = ValueSort(in.City)
	in.Subtype = ValueSort(in.Subtype)
	in.Industry = ValueSort(in.Industry)
	in.SelectType = ValueSort(in.SelectType)
	in.BuyerClass = ValueSort(in.BuyerClass)
	in.NotKey = ValueSort(in.NotKey)
	in.AdditionalWords = ValueSort(in.AdditionalWords)
	// 搜索分组为 1-招标采购公告时 2 超前项目
	// 当所选择的信息类型是全选时，需要处理成和全部时一样的空串
	switch in.SearchGroup {
	case util.SearchGroupBidding:
		if ValueSort(util.TopTypesBidding) == in.Subtype {
			in.Subtype = ""
		}
	case util.SearchGroupLeadingProject:
		if ValueSort(util.TopTypesLeadingProject) == in.Subtype {
			in.Subtype = ""
		}
	}

	inMap := common.StructToMapMore(in)
	inKey := GetKeysByParam(inMap)

	query["in_key"] = inKey
	res.Data = inKey
	if IC.Mgo.Count("search_condition", query) > 0 {
		res.ErrCode = 1
		res.ErrMsg = "该条件已保存，无需重复添加。"
	}
	return
}

func ValueSort(v string) string {
	vs := strings.Split(v, ",")
	sort.Slice(vs, func(i, j int) bool {
		return vs[i] < vs[j]
	})
	return strings.Join(vs, ",")
}

func GetKeysByParam(param map[string]interface{}) string {
	ps := &paramSorter{[]string{}, []string{}}
	for k, v := range param {
		ps.Keys = append(ps.Keys, k)
		ps.Values = append(ps.Values, common.InterfaceToStr(v))
	}
	ps.Sort()
	reqStr := ps.String()
	str := percentEncode(reqStr)
	str = SP(str, "%3A", "%253A", -1)
	return MD5(str)
}

func MD5(str string) string {
	data := []byte(str)
	has := md5.Sum(data)
	md5str := fmt.Sprintf("%x", has)
	return md5str
}

var SP = strings.Replace

func percentEncode(str string) string {
	str = url.QueryEscape(str)
	str = SP(SP(SP(str, "+", "%20", -1), "*", "%2A", -1), "%7E", "~", -1)
	return str
}

type paramSorter struct {
	Keys   []string
	Values []string
}

func (ps *paramSorter) String() string {
	str := ""
	for n, k := range ps.Keys {
		str += k + "=" + ps.Values[n]
		if n < len(ps.Keys)-1 {
			str += "&"
		}
	}
	return str
}

func (ps *paramSorter) Sort() {
	sort.Sort(ps)
}
func (ps *paramSorter) Len() int {
	return len(ps.Values)
}

func (ps *paramSorter) Less(i, j int) bool {
	return bytes.Compare([]byte(ps.Keys[i]), []byte(ps.Keys[j])) < 0
}

func (ps *paramSorter) Swap(i, j int) {
	ps.Values[i], ps.Values[j] = ps.Values[j], ps.Values[i]
	ps.Keys[i], ps.Keys[j] = ps.Keys[j], ps.Keys[i]
}
