package im

import (
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"git.rosy.net.cn/baseapi/platformapi/jdapi"
	"math/big"
	"strings"
	"time"

	"git.rosy.net.cn/jx-callback/business/model/dao"

	"git.rosy.net.cn/jx-callback/business/partner"

	"git.rosy.net.cn/jx-callback/business/model"

	"git.rosy.net.cn/baseapi/utils/errlist"

	"git.rosy.net.cn/jx-callback/globals"

	"git.rosy.net.cn/baseapi/platformapi/ebaiapi"

	"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
	"git.rosy.net.cn/baseapi/utils"
	push "git.rosy.net.cn/jx-callback/business/jxutils/unipush"
)

func SendVendorV2(data SendData, vendorOrgCode string) (err error) {
	switch data.VendorID {
	case model.VendorIDMTWM:
		dataStr, _ := json.Marshal(data.Data)
		if _, err = partner.CurAPIManager.GetAPI(model.VendorIDMTWM, vendorOrgCode).(*mtwmapi.API).MsgSend(string(dataStr)); err != nil {
			return err
		}
	case model.VendorIDEBAI:
		str, _ := json.Marshal(data.Data)
		param := &ebaiapi.BusinessSendMsgReq{}
		if err = json.Unmarshal(str, &param); err == nil {
			err = partner.CurAPIManager.GetAPI(model.VendorIDEBAI, vendorOrgCode).(*ebaiapi.API).BusinessSendMsg(param)
		}
	case model.VendorIDJD:
		str, _ := json.Marshal(data.Data)
		param := &jdapi.ContextMsg{}
		if err = json.Unmarshal(str, &param); err == nil {
			err = partner.CurAPIManager.GetAPI(model.VendorIDJD, vendorOrgCode).(*jdapi.API).MessagePushService(param)
		}
		if err != nil {
			return err
		}
	}

	err = ReadMsgFromClient(data.VendorID, vendorOrgCode, data.Data, data.StoreId)
	if err != nil {
		globals.SugarLogger.Debugf("SendVendorV2:%v", err)
	}
	return nil
}

type GetPoiIMStatusReq struct {
	VendorID      int    `json:"vendorID"`
	VendorStoreID string `json:"vendorStoreID"`
	VendorOrgCode string `json:"vendorOrgCode"`
}

type GetPoiIMStatusResp struct {
	VendorID int    `json:"vendorID"`
	ImStatus int    `json:"imStatus"`
	ErrMsg   string `json:"errMsg"`
}

// GetPoiIMStatus 查询门店IM单聊开关状态
func GetPoiIMStatus(param []GetPoiIMStatusReq) (retVal []*GetPoiIMStatusResp) {
	var (
		ans1 = &GetPoiIMStatusResp{}
		ans2 = &GetPoiIMStatusResp{}
	)
	if len(param) == 0 {
		return nil
	}
	for _, v := range param {
		switch v.VendorID {
		case model.VendorIDMTWM:
			api := partner.CurAPIManager.GetAPI(model.VendorIDMTWM, v.VendorOrgCode).(*mtwmapi.API)
			switch v.VendorOrgCode {
			case "5873":
				storeDetail, err := dao.GetStoreDetailByVendorStoreID(dao.GetDB(), v.VendorStoreID, model.VendorIDMTWM, v.VendorOrgCode)
				if err != nil || storeDetail == nil {
					return nil
				}
				api.SetToken(storeDetail.MtwmToken)
			default:

			}
			temp, err := api.GetPoiIMStatus(v.VendorStoreID)
			if err != nil {
				ans1.ErrMsg = fmt.Sprintf("1:%v", err)
				continue
			}
			ans1.VendorID = model.VendorIDMTWM
			ans1.ImStatus = temp.ImStatus
		case model.VendorIDEBAI:
			status, err := partner.CurAPIManager.GetAPI(model.VendorIDEBAI, v.VendorOrgCode).(*ebaiapi.API).GetStoreIMStatus(v.VendorStoreID)
			if err != nil {
				ans1.ErrMsg = fmt.Sprintf("3:%v", err)
				continue
			}
			ans2.VendorID = model.VendorIDEBAI
			ans2.ImStatus = utils.Str2Int(status)
		case model.VendorIDJD:
			//api := partner.CurAPIManager.GetAPI(model.VendorIDJD, v.VendorOrgCode).(*jdapi.API)
			//api.ImWaiterStatusModify()
		}
	}
	retVal = append(retVal, ans1, ans2)
	return retVal
}

type SetPoiIMStatusReq struct {
	VendorID      int    `json:"vendorID"`
	VendorStoreID string `json:"vendorStoreID"`
	VendorOrgCode string `json:"vendorOrgCode"`
	ImStatus      int    `json:"imStatus"`
}

// SetPoiIMStatus 设置平台门店im状态
func SetPoiIMStatus(param []SetPoiIMStatusReq) error {
	var errList errlist.ErrList
	if len(param) == 0 {
		return nil
	}
	for _, v := range param {
		switch v.VendorID {
		case model.VendorIDMTWM:
			if err := partner.CurAPIManager.GetAPI(model.VendorIDMTWM, v.VendorOrgCode).(*mtwmapi.API).SetPoiIMStatus(v.VendorStoreID, v.ImStatus); err != nil {
				errList.AddErr(fmt.Errorf("mtwm:%v", err))
			}
		case model.VendorIDEBAI:
			if err := partner.CurAPIManager.GetAPI(model.VendorIDEBAI, v.VendorOrgCode).(*ebaiapi.API).UpdateIMStatus(v.VendorStoreID, v.ImStatus); err != nil {
				errList.AddErr(fmt.Errorf("ebai:%v", err))
			}
		case model.VendorIDJD:
			api := partner.CurAPIManager.GetAPI(model.VendorIDJD, v.VendorOrgCode).(*jdapi.API)
			api.ImStatusModify(fmt.Sprintf("%s+%s", v.VendorStoreID, v.VendorOrgCode), 0, true)
			// 0：忙碌；1：在线
			err := api.ImWaiterStatusModify(1, v.VendorStoreID, v.ImStatus)
			errList.AddErr(fmt.Errorf("jd:%v", err))
		}
	}
	return errList.GetErrListAsOne()
}

// ReadMsgFromClient 存储客户端发送的消息
func ReadMsgFromClient(vendorID int, elmAppID string, msg interface{}, storeId int) error {
	var (
		err      error
		elmTime  int
		jxMsg    = &JXMsg{}
		errList  errlist.ErrList
		userList = &UserMessageList{}
	)

	data, err := json.Marshal(msg)
	if err != nil {
		errList.AddErr(fmt.Errorf("json处理数据错误：%v", err))
	}

	switch vendorID {
	case model.VendorIDMTWM:
		var pushContent = mtwmapi.PushContentReq{}
		err = json.Unmarshal(data, &pushContent)
		jxMsg = &JXMsg{
			SendType:   SendTypeJx,
			MsgContent: pushContent,
		}
		userList = &UserMessageList{
			VendorID:   model.VendorIDMTWM,
			UserID:     utils.Int2Str(pushContent.OpenUserID),
			LatestMsg:  pushContent.MsgContent,
			LatestTime: pushContent.Cts,
			OrderID:    "",
		}
		if pushContent.OrderID != 0 {
			userList.OrderID = utils.Int2Str(pushContent.OrderID)
		}
	case model.VendorIDEBAI:
		var ElmData = ebaiapi.ImMessageSend{}
		err = json.Unmarshal(data, &ElmData)
		jxMsg = &JXMsg{
			SendType:   SendTypeJx,
			MsgContent: ElmData,
		}
		if ElmData.PayLoad.CreateTime == 0 {
			elmTime = int(time.Now().Unix())
		}
		userList = &UserMessageList{
			VendorID:   model.VendorIDEBAI,
			UserID:     ElmData.PayLoad.GroupID,
			LatestMsg:  ElmData.PayLoad.Content,
			LatestTime: elmTime,
		}
	case model.VendorIDJD:
		var jdData = jdapi.ContextMsg{}
		if err = json.Unmarshal(data, &jdData); err == nil {
			store, err := dao.GetStoreDetail(dao.GetDB(), storeId, model.VendorIDJD, elmAppID)
			if err != nil {
				return err
			}
			shopInfo := &jdapi.JdParamJsonObj{
				StatusId:       utils.Int2Str(storeId), // 京西门店ID
				BillId:         elmAppID,               // vendorOrgCode
				ExtendJsonData: "",
				StoreId:        store.VendorStoreID, // 平台门店ID
				Timestamp:      utils.Time2Str(time.Now()),
			}
			extendJsonData := &jdapi.UserChatMsg{
				Id:   jdData.Id,
				Lang: jdData.Lang,
				Type: jdData.Type,
				From: struct {
					Pin        string `json:"pin"`
					App        string `json:"app"`
					ClientType string `json:"clientType"`
				}{
					Pin:        jdData.From.Pin,
					App:        jdData.From.App,
					ClientType: jdData.From.ClientType,
				},
				To: struct {
					Pin        string `json:"pin"`
					App        string `json:"app"`
					ClientType string `json:"clientType"`
				}{
					Pin:        jdData.To.Pin,
					App:        jdData.To.App,
					ClientType: "",
				},
				Body: jdapi.UserChatMsgBody{
					Content: jdData.Body.Content,
					Type:    jdData.Body.Type,
				},
				Timestamp:  jdData.Timestamp,
				ClientTime: jdData.ClientTime,
			}
			shopInfo.ExtendJsonData = string(utils.MustMarshal(extendJsonData))

			jxMsg = &JXMsg{
				SendType:   SendTypeJx,
				MsgContent: shopInfo,
			}
			userList = &UserMessageList{
				VendorID:   model.VendorIDJD,
				UserID:     jdData.To.Pin,
				LatestMsg:  jdData.Body.Content,
				LatestTime: int(time.Now().Unix()),
			}
		}

	}
	//1 存储展示列表时单条数据
	if err = SetMessageDetail(jxMsg, vendorID, elmAppID); err != nil {
		errList.AddErr(fmt.Errorf("存储详细聊天记录错误：%v", err))
	}
	//2 存储详细聊天记录list
	if err = SetUserList(jxMsg, userList, vendorID, elmAppID); err != nil {
		errList.AddErr(fmt.Errorf("存储STU聊天记录错误：%v", err))
	}
	if errList.GetErrListAsOne() != nil {
		return fmt.Errorf("ReadMsgFromClient:%v", errList.GetErrListAsOne())
	}
	return nil
}

// ReadMsgFromVendor 读取数据并存储到redis 回调
func ReadMsgFromVendor(vendorID int, elmAppID string, msg []byte) error {
	var (
		err                         error
		jxMsg                       = &JXMsg{}
		vendorStoreID               string
		errList                     errlist.ErrList
		userList                    = &UserMessageList{}
		systemMsg, userMsg, readMsg = &jdapi.ChatRisInfo{}, &jdapi.UserChatMsg{}, &jdapi.UserMsgReadAck{}
	)
	if len(string(msg)) == 0 {
		errList.AddErr(fmt.Errorf("读取平台数据为空，请检查"))
	}

	switch vendorID {
	case model.VendorIDMTWM:
		var PushContentReq = mtwmapi.PushContentReq{}
		err = json.Unmarshal(msg, &PushContentReq)
		if len(PushContentReq.MsgContent) != 0 || PushContentReq.MsgContent != "" {
			if FilterIm(PushContentReq.AppID, PushContentReq.MsgContent) { //自动回复消息过滤
				return nil
			}
		}

		jxMsg = &JXMsg{
			SendType:   SendTypeMt,
			MsgContent: PushContentReq,
		}
		userList = &UserMessageList{
			VendorID:   model.VendorIDMTWM,
			UserID:     utils.Int2Str(PushContentReq.OpenUserID),
			LatestMsg:  PushContentReq.MsgContent,
			LatestTime: PushContentReq.Cts,
		}
		vendorStoreID = PushContentReq.AppPoiCode
		if PushContentReq.OrderID != 0 {
			userList.OrderID = utils.Int2Str(PushContentReq.OrderID)
		}
	case model.VendorIDEBAI:
		var ElmData = ebaiapi.ImMessageSend{}
		err = json.Unmarshal(msg, &ElmData)
		jxMsg = &JXMsg{
			SendType:   SendTypeElm,
			MsgContent: ElmData,
		}
		userList = &UserMessageList{
			VendorID:   model.VendorIDEBAI,
			UserID:     ElmData.PayLoad.GroupID,
			LatestMsg:  ElmData.PayLoad.Content,
			LatestTime: int(ElmData.PayLoad.CreateTime / 1000),
		}
		vendorStoreID = ElmData.PlatformShopID
	case model.VendorIDJD:
		var risMsg *jdapi.JdParamJsonObj
		if err = utils.UnmarshalUseNumber(msg, &risMsg); err != nil {
			return err
		}
		storeDetail, err := dao.GetStoreDetailByVendorStoreID(dao.GetDB(), risMsg.StoreId, model.VendorIDJD, "")
		if err != nil {
			return err
		}
		risMsg.BillId = storeDetail.VendorOrgCode
		jxMsg = &JXMsg{
			SendType:   SendTypeJd,
			MsgContent: risMsg,
		}
		systemMsg, userMsg, readMsg, err = jdapi.ImMsgChange(risMsg, elmAppID)
		if err != nil {
			return err
		}
		userList = &UserMessageList{
			VendorID: model.VendorIDJD,
			MsgFrom:  elmAppID,
		}
		switch elmAppID {
		case jdapi.ImCallbackRisMsg:
			return nil
			userList.UserID = systemMsg.From.Pin
			userList.LatestTime = int(systemMsg.Timestamp)
			userList.LatestMsg = "暂无"
		case jdapi.ImCallbackUserMsg:
			userList.UserID = userMsg.From.Pin
			userList.LatestTime = int(userMsg.Timestamp)
			userList.LatestMsg = userMsg.Body.Content
		case jdapi.ImCallbackReadMsg:
			return nil
			userList.UserID = readMsg.From.Pin
			userList.LatestTime = int(readMsg.Timestamp)
			userList.LatestMsg = "暂无"
		}
		vendorStoreID = risMsg.StoreId
	}

	//1 存储详细聊天记录list
	if err = SetMessageDetail(jxMsg, vendorID, elmAppID); err != nil {
		errList.AddErr(fmt.Errorf("存储详细聊天记录错误：%v", err))
	}
	//2 存储展示列表时单条数据
	if err = SetUserList(jxMsg, userList, vendorID, elmAppID); err != nil {
		errList.AddErr(fmt.Errorf("存储STU聊天记录错误：%v", err))
	}
	//3 cid推送新消息
	switch vendorID {
	case model.VendorIDEBAI, model.VendorIDMTWM:
		if err = PushMsgByCid(vendorStoreID, vendorID, string(msg)); err != nil {
			errList.AddErr(fmt.Errorf("向商家cid推送新消息错误：%v", err))
		}
	case model.VendorIDJD:
		if elmAppID == jdapi.ImCallbackUserMsg {
			err = PushMsgByCid(vendorStoreID, vendorID, "京东用户发送聊天消息,请及时查看")
		}
		if err != nil {
			errList.AddErr(fmt.Errorf("京东向商家cid推送新消息错误：%v", err))
		}
	}

	//4 客服自动回复
	if err = CheckAndReply(jxMsg, elmAppID); err != nil {
		errList.AddErr(fmt.Errorf("客服自动回复出错：%v", err))
	}

	//5延迟40s 自动回复
	//timer := time.NewTimer(30 * time.Second)

	if errList.GetErrListAsOne() != nil {
		return fmt.Errorf("ReadMsgFromVendor:%v", errList.GetErrListAsOne())
	}
	return nil
}

// PushMsgByCid 通过cid push用户
func PushMsgByCid(vendorStoreID string, vendorID int, msg string) error {
	if err := push.NotifyImNewMessage(vendorStoreID, vendorID, msg); err != nil {
		return err
	}
	return nil
}

// SetMessageDetail 赋值
//格式 AppID:AppPoiCode:1:OpenUserID
func SetMessageDetail(req *JXMsg, vendorID int, elmAppID string) error {
	if req == nil {
		return nil
	}
	//生成京西消息ID detail
	msgID := GenMsgDetailID(req, vendorID, elmAppID)
	if len(msgID) == 0 {
		return nil
	}

	data, _ := json.Marshal(req)
	err := rdb.RPush(msgID, string(data))
	ok, err := rdb.ExpireResult(msgID, ExpireTimeDay)
	if err != nil || !ok {
		return err
	}
	return nil
}

// SetUserList 赋值
//AppPoiCode:10 [userid1:{SingleChat},userid2:{}]
func SetUserList(jxMsg *JXMsg, userList *UserMessageList, vendorID int, elmAppID string) error {
	//生成msgID
	msgID := GenMsgListID(jxMsg, vendorID, elmAppID)
	if len(msgID) == 0 {
		return nil
	}

	//获取未读消息条数并删除旧数据
	cnt, err := GetNewAndTrim(msgID, userList.UserID)
	if cnt > 0 {
		userList.NewMessageNum = cnt
	} else {
		userList.NewMessageNum = 1
	}
	//存储当前数据
	data, _ := json.Marshal(userList)
	err = rdb.RPush(msgID, string(data))
	ok, err := rdb.ExpireResult(msgID, ExpireTimeDay)
	if err != nil || !ok {
		return err
	}
	return nil
}

// GetNewAndTrim   获取未读条数并清除旧数据
func GetNewAndTrim(key string, flag string) (cnt int, err error) {
	cnt = 0
	if n, err := rdb.Exists(key); n > 0 && err == nil {
		s2 := rdb.LRange(key)
		for i := 0; i < len(s2); i++ {
			v := UserMessageList{}
			_ = json.Unmarshal([]byte(s2[i]), &v)
			if v.UserID == flag {
				err = rdb.LSet(key, i, "del")
				err = rdb.LRem(key, 0, "del")
				s2 = append(s2[:i], s2[i+1:]...)
				i--
				if v.NewMessageNum == 0 { //目前为首条
					cnt++ //赋值1
				} else {
					cnt = v.NewMessageNum
				}
			}
		}
	} else {
		return 0, nil
	}
	return cnt, err
}

// GenMsgDetailID 生成查询详细聊天记录ID
func GenMsgDetailID(jxMsg *JXMsg, vendorID int, elmAppID string) (msgID string) {
	if jxMsg == nil {
		return ""
	}
	switch vendorID {
	case model.VendorIDMTWM:
		var d1 = jxMsg.MsgContent.(mtwmapi.PushContentReq)
		msgID = utils.Int2Str(d1.AppID) + ":" + d1.AppPoiCode + ":1:" + utils.Int2Str(d1.OpenUserID)
	case model.VendorIDEBAI:
		var ElmData = ebaiapi.ImMessageSend{}
		tempMsgContent, _ := json.Marshal(jxMsg.MsgContent)
		if err := json.Unmarshal(tempMsgContent, &ElmData); err != nil {
			return ""
		}
		//var d2 = jxMsg.MsgContent.(ebaiapi.ImMessageSend)
		//msgID = elmAppID + ":" + d2.PlatformShopID + ":3:" + d2.PayLoad.GroupID
		msgID = elmAppID + ":" + ElmData.PlatformShopID + ":3:" + ElmData.PayLoad.GroupID
	case model.VendorIDJD:
		var data = jxMsg.MsgContent.(*jdapi.JdParamJsonObj)
		msgID = data.BillId + ":" + data.StoreId + ":0:"
		if jxMsg.SendType == SendTypeJx {
			elmAppID = jdapi.ImCallbackUserMsg
		}
		systemMsg, userMsg, readMsg, _ := jdapi.ImMsgChange(data, elmAppID)
		switch elmAppID {
		case jdapi.ImCallbackRisMsg:
			msgID += systemMsg.To.Pin
		case jdapi.ImCallbackUserMsg:
			msgID += userMsg.To.Pin
		case jdapi.ImCallbackReadMsg:
			msgID += readMsg.To.Pin
		}
	}
	return msgID
}

// GenMsgListID 生成展示列表时单条数据ID（部分）
func GenMsgListID(jxMsg *JXMsg, vendorID int, elmAppID string) (msgID string) {
	if jxMsg == nil {
		return ""
	}
	switch vendorID {
	case model.VendorIDMTWM:
		var d1 = jxMsg.MsgContent.(mtwmapi.PushContentReq)
		msgID = utils.Int2Str(d1.AppID) + ":" + d1.AppPoiCode + ":1"
	case model.VendorIDEBAI:
		var ElmData = ebaiapi.ImMessageSend{}
		tempMsgContent, _ := json.Marshal(jxMsg.MsgContent)
		json.Unmarshal(tempMsgContent, &ElmData)
		msgID = elmAppID + ":" + ElmData.PlatformShopID + ":3"
	case model.VendorIDJD:
		var data = jxMsg.MsgContent.(*jdapi.JdParamJsonObj)
		msgID = data.BillId + ":" + data.StoreId + ":0"
	}

	return msgID
}

// GetImUserList 获取门店用户聊天列表
func GetImUserList(req []RelInfo) (map[string][]interface{}, error) {
	retVal := make(map[string][]interface{}, 0)
	if len(req) == 0 {
		return nil, errors.New("msgID不允许为空")
	}
	var keys []string
	for _, i := range req {
		key := i.AppID + ":" + i.VendorStoreID + ":" + i.VendorID
		keys = append(keys, key)
	}
	for _, j := range keys {
		temp := rdb.LRange(j)
		for _, v := range temp {
			//过滤过期信息
			if FilterUserList(v) {
				retVal[j] = append(retVal[j], v)
			}
		}
	}
	return retVal, nil
}

func FilterUserList(val string) bool {
	retVal := UserMessageList{}
	err := json.Unmarshal([]byte(val), &retVal)
	if err != nil || time.Now().Unix()-int64(retVal.LatestTime) >= 3600*6 {
		return false
	}
	return true
}

// FilterChatDetail 去重
func FilterChatDetail(req *JXMsg, vendorID int) {
	//if vendorID == VendorIDMT {
	//	mt := req.MsgContent.(mtwmapi.PushContentReq)
	//	temp, _ := GetImChatDetail([]UserRelInfo{{
	//		VendorStoreID: mt.AppPoiCode,
	//		VendorID:      "1",
	//		AppID:         utils.Int2Str(mt.AppID),
	//		UserID:        utils.Int2Str(mt.OpenUserID),
	//	}})
	//
	//}
	//
	//if vendorID == VendorIDELM {
	//	elm := req.MsgContent.(ebaiapi.ImMessageSend)
	//	temp, _ := GetImChatDetail([]UserRelInfo{{
	//		VendorStoreID: elm.PlatformShopID,
	//		VendorID:      "3",
	//		AppID:         "34665",
	//		UserID:        elm.PayLoad.SenderID,
	//	}})
	//}
}

// GetImChatDetail 获取门店用户聊天详情
func GetImChatDetail(req []UserRelInfo) (map[string][]interface{}, error) {
	retVal := make(map[string][]interface{}, 0)
	if len(req) == 0 {
		return nil, errors.New("msgID不允许为空")
	}
	var keys []string
	for _, i := range req {
		key := i.AppID + ":" + i.VendorStoreID + ":" + i.VendorID + ":" + i.UserID
		keys = append(keys, key)
	}
	for _, j := range keys {
		temp := rdb.LRange(j)
		for _, v := range temp {
			retVal[j] = append(retVal[j], v)
			//retVal["chatDetail"] = append(retVal["chatDetail"], v)
		}
	}
	return retVal, nil
}

// SetJxMsgRead   设置jx消息已读 userID(美团：openUserID;饿了么：groupID)
func SetJxMsgRead(appID, vendorStoreID, vendorID, userID string) error {
	var (
		temp = UserMessageList{}
		key  = appID + ":" + vendorStoreID + ":" + vendorID
	)
	if n, err := rdb.Exists(key); n > 0 && err == nil {
		s2 := rdb.LRange(key)
		for i := 0; i < len(s2); i++ {
			v := UserMessageList{}
			_ = json.Unmarshal([]byte(s2[i]), &v)
			if v.UserID == userID {
				//删除此条数据
				err = rdb.LSet(key, i, "del")
				err = rdb.LRem(key, 0, "del")
				s2 = append(s2[:i], s2[i+1:]...)
				i--
				//cnt=0 重新赋值
				temp = UserMessageList{
					VendorID:      v.VendorID,
					UserID:        v.UserID,
					OrderID:       v.OrderID,
					NewMessageNum: 0,
					LatestMsg:     v.LatestMsg,
					LatestTime:    v.LatestTime,
				}
			}
		}
		str, _ := json.Marshal(temp)
		err = rdb.RPush(key, str)
	}
	return nil
}

// AutoReply 是否已回复
//key=AppID+:+UserID+:+msgID(mt)
//key=AppID+:+UserID+:+msgID(elm)
type AutoReply struct {
	UserID    int  `json:"userID"`
	MsgID     int  `json:"msgID"`     //消息ID
	IsApply   bool `json:"IsApply"`   //是否已回复
	Timestamp int  `json:"timestamp"` //消息接收时间
}

// CheckAndReply 判断并回复V1
func CheckAndReply(req *JXMsg, elmAppID string) (err error) {
	var (
		key string
		//keyDetail UserRelInfo
		flag     = false
		vendorID int
		errList  errlist.ErrList
		apply    *AutoReply
		jxMsg    = &JXMsg{}
		//userList = &UserMessageList{}
	)

	switch req.SendType {
	case SendTypeMt:
		vendorID = model.VendorIDMTWM
		mt := req.MsgContent.(mtwmapi.PushContentReq)
		//跳过12小时内商家消息自动回复
		if mt.MsgSource != mtwmapi.MsgSourceUser {
			return nil
		}

		key = utils.Int2Str(mt.AppID) + ":" + utils.Int2Str(mt.OpenUserID) + ":autoReply"
		keyDetailMt := UserRelInfo{
			AppID:         utils.Int2Str(mt.AppID),
			VendorStoreID: mt.AppPoiCode,
			VendorID:      utils.Int2Str(model.VendorIDMTWM),
			UserID:        utils.Int2Str(mt.OpenUserID),
		}
		//1 检测是否已自动回复
		flag = GetIfReply(key, keyDetailMt)
		//判断flag状态
		if !flag {
			apply = &AutoReply{
				UserID:    mt.AppID,
				MsgID:     mt.MsgID,
				IsApply:   true,
				Timestamp: mt.Cts,
			}

			temp := mt
			//获取自定义回复模板
			if template := GetCustomTemplate(utils.Int2Str(mt.AppID), mt.AppPoiCode); len(template.Template) > 0 {
				// 关闭自动回复
				if template.Template == "3ASOkN9WiU3AUae2tYGChA==" {
					return nil
				}
				temp.MsgContent = template.Template
			} else {
				temp.MsgContent, err = GetDefaultTemplate(utils.Int2Str(mt.AppID), mt.AppPoiCode, model.VendorIDMTWM)
				if err != nil {
					temp.MsgContent = AutoReplyByAppID[mt.AppID]
				}
			}
			temp.MsgType = mtwmapi.MsgTypeText
			temp.MsgSource = mtwmapi.MsgSourceStore
			temp.Cts = int(time.Now().Unix())
			temp.MsgID = RandTimeNumber()

			dataStr, _ := json.Marshal(temp)
			if _, err = partner.CurAPIManager.GetAPI(model.VendorIDMTWM, utils.Int2Str(mt.AppID)).(*mtwmapi.API).MsgSend(string(dataStr)); err != nil {
				apply.IsApply = false
				globals.SugarLogger.Debugf("CheckAndReply mtSend err:%v", err)
			} else {
				jxMsg = &JXMsg{
					SendType:   SendTypeJx,
					MsgContent: temp,
				}

				// 存储详细聊天记录
				if err = SetMessageDetail(jxMsg, vendorID, elmAppID); err != nil {
					errList.AddErr(fmt.Errorf("自动回复：存储详细聊天记录错误：%v", err))
				}
			}
			//3 记录自动回复状态
			if err = RecordAutoStatus(key, apply); err != nil {
				errList.AddErr(fmt.Errorf("自动回复：记录自动回复状态错误：%v", err))
			}
		}
	case SendTypeElm:
		vendorID = model.VendorIDEBAI
		elm := req.MsgContent.(ebaiapi.ImMessageSend)
		key = elmAppID + ":" + elm.PayLoad.SenderID + ":autoReply"

		if elm.PayLoad.SenderID == "" || elm.PayLoad.SenderID[:2] != ebaiapi.SenderTypeUser {
			return nil
		}

		keyDetailElm := UserRelInfo{
			AppID:         elmAppID,
			VendorStoreID: elm.PlatformShopID,
			VendorID:      utils.Int2Str(model.VendorIDEBAI),
			UserID:        elm.PayLoad.GroupID,
		}
		//1 检测是否已自动回复
		flag = GetIfReply(key, keyDetailElm)
		if !flag {
			apply = &AutoReply{
				UserID:    utils.Str2Int(elm.PayLoad.SenderID),
				MsgID:     utils.Str2Int(elm.PayLoad.MsgID),
				IsApply:   true,
				Timestamp: elm.PayLoad.CreateTime,
			}

			param := &ebaiapi.BusinessSendMsgReq{
				PlatformShopId: elm.PlatformShopID,
				BizType:        ebaiapi.IMType,
				SubBizType:     ebaiapi.IMTypeSendMsg,
				PayLoad: ebaiapi.BusinessMsgPayload{
					GroupId:     elm.PayLoad.GroupID,
					MsgId:       utils.Int2Str(RandTimeNumber()),
					ReceiverIds: elm.PayLoad.ReceiverIDs,
					ContentType: utils.Int2Str(ebaiapi.ContentTypeNormal),
				},
			}

			temp := ""
			if template := GetCustomTemplate(elmAppID, elm.PlatformShopID); len(template.Template) > 0 {
				temp = template.Template
			} else {
				temp, err = GetDefaultTemplate(elmAppID, elm.PlatformShopID, model.VendorIDEBAI)
				if err != nil {
					temp = LastTemplate
				}
			}
			tempStr, _ := json.Marshal(temp)
			tempContent := ebaiapi.Content{
				Text: string(tempStr),
				//Text: temp,
			}
			tempContentStr, _ := json.Marshal(tempContent)

			param.PayLoad.Content = string(tempContentStr)

			if err = partner.CurAPIManager.GetAPI(model.VendorIDEBAI, elmAppID).(*ebaiapi.API).BusinessSendMsg(param); err != nil {
				apply.IsApply = false
				globals.SugarLogger.Debugf("CheckAndReply mtSend err:%v", err)
			} else {

				jxMsg = &JXMsg{
					SendType:   SendTypeJx,
					MsgContent: param,
				}

				//存储详细聊天记录list
				if err = SetMessageDetail(jxMsg, vendorID, elmAppID); err != nil {
					errList.AddErr(fmt.Errorf("自动回复：存储详细聊天记录错误：%v", err))
				}
			}
			//3 记录自动回复状态
			if err = RecordAutoStatus(key, apply); err != nil {
				errList.AddErr(fmt.Errorf("自动回复：记录自动回复状态错误：%v", err))
			}
		}
	case SendTypeJd:
		// 京东暂时有自动回复功能
		//vendorID = model.VendorIDJD
		//jd := req.MsgContent.(*jdapi.ChatRisMsgCallback)
		////跳过12小时内商家消息自动回复
		//if elmAppID != jdapi.ImCallbackUserMsg {
		//	return nil
		//}
		//var userMsg *jdapi.UserChatMsg
		//if err = utils.UnmarshalUseNumber([]byte(jd.ExtendJsonData), &userMsg); err != nil {
		//	return err
		//}
		//
		//key = jd.VenderId + ":" + userMsg.From.Pin + ":autoReply"
		//keyDetailMt := UserRelInfo{
		//	AppID:         jd.VenderId,
		//	VendorStoreID: jd.StationId,
		//	VendorID:      utils.Int2Str(model.VendorIDJD),
		//	UserID:        userMsg.From.Pin,
		//}
		////1 检测是否已自动回复
		//flag = GetIfReply(key, keyDetailMt)
		////判断flag状态
		//if !flag {
		//	apply = &AutoReply{
		//		UserID:    1,
		//		MsgID:     1,
		//		IsApply:   true,
		//		Timestamp: int(userMsg.Timestamp),
		//	}
		//	//jdapi.ContextMsg{}
		//	temp := ""
		//	//获取自定义回复模板
		//	if template := GetCustomTemplate(jd.VenderId, jd.StationId); len(template.Template) > 0 {
		//		temp = template.Template
		//	} else {
		//		temp, err = GetDefaultTemplate(jd.VenderId, jd.StationId, model.VendorIDJD)
		//		if err != nil {
		//			temp = LastTemplate
		//		}
		//	}
		//
		//	uuid := utils.GetUUID()
		//	autoReplayParam := &jdapi.ContextMsg{
		//		Id:   uuid,
		//		Lang: "zh_CN",
		//		Type: "chat_message",
		//		From: jdapi.ContextFrom{
		//			Pin:        userMsg.From.Pin,
		//			App:        "im.waiter",
		//			ClientType: "gw",
		//		},
		//		To: jdapi.ContextTo{
		//			Pin: userMsg.To.Pin,
		//			App: "im.customer",
		//		},
		//		Body: jdapi.ContextBody{
		//			Type:    "text",
		//			Content: temp,
		//			Chatinfo: jdapi.ContextBodyChatInfo{
		//				VenderId:        jd.VenderId,
		//				AskAllocateType: "multiChat",
		//				Sid:             userMsg.Body.(map[string]interface{})["chatinfo"].(map[string]interface{})["sid"].(string),
		//				Source:          fmt.Sprintf("dd_msg_?_%s"?, uuid),
		//			},
		//			Template: struct {
		//				Source string `json:"source"`
		//			}{
		//				Source: fmt.Sprintf("dd_msg_?_%s"?, uuid),
		//			},
		//			Mt: 60,
		//		},
		//		Timestamp:  time.Now().UnixNano(),
		//		ClientTime: time.Now().UnixNano(),
		//	}
		//	if err = partner.CurAPIManager.GetAPI(model.VendorIDJD, jd.VenderId).(*jdapi.API).MessagePushService(autoReplayParam); err != nil {
		//		apply.IsApply = false
		//		globals.SugarLogger.Debugf("CheckAndReply jd send err:%v", err)
		//	} else {
		//		jxMsg = &JXMsg{
		//			SendType:   SendTypeJx,
		//			MsgContent: temp,
		//		}
		//		// 存储详细聊天记录
		//		if err = SetMessageDetail(jxMsg, vendorID, elmAppID); err != nil {
		//			errList.AddErr(fmt.Errorf("自动回复：存储详细聊天记录错误：%v", err))
		//		}
		//	}
		//	//3 记录自动回复状态
		//	if err = RecordAutoStatus(key, apply); err != nil {
		//		errList.AddErr(fmt.Errorf("自动回复：记录自动回复状态错误：%v", err))
		//	}
		//}
	}

	if errList.GetErrListAsOne() != nil {
		return fmt.Errorf("CheckAndReply err=%v", errList.GetErrListAsOne())
	}
	return nil
}

// CheckAndReplyV2 判断并回复V2 延迟35s
//func CheckAndReplyV2(req *JXMsg, elmAppID string) (err error) {
//	var (
//		key      string
//		vendorID int
//		errList  errlist.ErrList
//		jxMsg    = &JXMsg{}
//	)
//
//	if req.SendType == SendTypeMt {
//		vendorID = VendorIDMT
//		mt := req.MsgContent.(mtwmapi.PushContentReq)
//		//获取聊天详情
//		imDetail, err := GetImChatDetail([]UserRelInfo{{
//			VendorStoreID: mt.AppPoiCode,
//			VendorID:      VendorIDMTStr,
//			AppID:         utils.Int2Str(mt.AppID),
//			UserID:        utils.Int2Str(mt.OpenUserID),
//		}})
//		if err != nil {
//			return err
//		}
//		if len(imDetail) > 0 {
//			//获取此消息列表最后一条数据
//			key = GenMsgDetailID(req, VendorIDMT, elmAppID)
//			temp := imDetail[key][len(imDetail)-1]
//			tStr, _ := json.Marshal(temp)
//
//			lastMsg := &JXMsg{}
//			err = json.Unmarshal(tStr, lastMsg)
//			if err != nil {
//				return err
//			}
//			//京西发送或美团商家发送 跳过
//			if lastMsg.SendType == SendTypeJx {
//				return nil
//			}
//
//			lastMt := lastMsg.MsgContent.(mtwmapi.PushContentReq)
//			if lastMt.MsgSource == mtwmapi.MsgSourceStore {
//				return nil
//			}
//
//			//生成回复消息体
//			sendMt := mt
//			//获取自定义回复模板
//			if template := GetCustomTemplate(utils.Int2Str(mt.AppID), mt.AppPoiCode); len(template) > 0 {
//				sendMt.MsgContent = template
//			} else {
//				sendMt.MsgContent, err = GetDefaultTemplate(utils.Int2Str(mt.AppID), mt.AppPoiCode, VendorIDMT)
//				if err != nil {
//					sendMt.MsgContent = AutoReplyByAppID[mt.AppID]
//				}
//			}
//			sendMt.MsgType = mtwmapi.MsgTypeText
//			sendMt.MsgSource = mtwmapi.MsgSourceStore
//			sendMt.Cts = int(time.Now().Unix())
//			sendMt.MsgID = RandTimeNumber()
//
//			//向美团发送消息
//			dataStr, _ := json.Marshal(sendMt)
//			if _, err = partner.CurAPIManager.GetAPI(model.VendorIDMTWM, utils.Int2Str(mt.AppID)).(*mtwmapi.API).MsgSend(string(dataStr)); err != nil {
//				globals.SugarLogger.Debugf("CheckAndReply mtSend err:%v", err)
//				return err
//			} else {
//				jxMsg = &JXMsg{
//					SendType:   SendTypeJx,
//					MsgContent: temp,
//				}
//				if err = SetMessageDetail(jxMsg, vendorID, elmAppID); err != nil {
//					errList.AddErr(fmt.Errorf("自动回复V2：存储详细聊天记录错误：%v", err))
//				}
//			}
//		}
//	}
//
//	if req.SendType == SendTypeElm {
//		vendorID = VendorIDELM
//		elm := req.MsgContent.(ebaiapi.ImMessageSend)
//		imDetail, err := GetImChatDetail([]UserRelInfo{{
//			VendorStoreID: elm.PlatformShopID,
//			VendorID:      VendorIDELMStr,
//			AppID:         elmAppID,
//			UserID:        elm.PayLoad.SenderID,
//		}})
//		if err != nil {
//			return err
//		}
//		if len(imDetail) > 0 {
//			//获取此消息列表最后一条数据
//			key = GenMsgDetailID(req, VendorIDELM, elmAppID)
//			temp := imDetail[key][len(imDetail)-1]
//			tStr, _ := json.Marshal(temp)
//
//			lastMsg := &JXMsg{}
//			err = json.Unmarshal(tStr, lastMsg)
//			if err != nil {
//				return err
//			}
//			//京西发送或美团商家发送 跳过
//			if lastMsg.SendType == SendTypeJx {
//				return nil
//			}
//
//			//结构不一样后解
//			lastElm := lastMsg.MsgContent.(ebaiapi.ImMessageSend)
//			if lastElm.PayLoad.SenderID == "" || elm.PayLoad.SenderID[:2] != ebaiapi.SenderTypeUser {
//				return nil
//			}
//
//			param := &ebaiapi.BusinessSendMsgReq{
//				PlatformShopId: elm.PlatformShopID,
//				BizType:        ebaiapi.IMType,
//				SubBizType:     ebaiapi.IMTypeSendMsg,
//				PayLoad: ebaiapi.BusinessMsgPayload{
//					GroupId:     elm.PayLoad.GroupID,
//					MsgId:       utils.Int2Str(RandTimeNumber()),
//					ReceiverIds: elm.PayLoad.ReceiverIDs,
//					ContentType: utils.Int2Str(ebaiapi.ContentTypeNormal),
//				},
//			}
//
//			data := ""
//			if template := GetCustomTemplate(elmAppID, elm.PlatformShopID); len(template) > 0 {
//				data = template
//			} else {
//				data, err = GetDefaultTemplate(elmAppID, elm.PlatformShopID, VendorIDELM)
//				if err != nil {
//					data = LastTemplate
//				}
//			}
//			dataStr, _ := json.Marshal(data)
//			tempContent := ebaiapi.Content{
//				Text: string(dataStr),
//			}
//			tempContentStr, _ := json.Marshal(tempContent)
//			param.PayLoad.Content = string(tempContentStr)
//
//			if err = partner.CurAPIManager.GetAPI(model.VendorIDEBAI, elmAppID).(*ebaiapi.API).BusinessSendMsg(param); err != nil {
//				globals.SugarLogger.Debugf("CheckAndReply mtSend err:%v", err)
//				return err
//			} else {
//				jxMsg = &JXMsg{
//					SendType:   SendTypeJx,
//					MsgContent: param,
//				}
//				if err = SetMessageDetail(jxMsg, vendorID, elmAppID); err != nil {
//					errList.AddErr(fmt.Errorf("自动回复V2：存储详细聊天记录错误：%v", err))
//				}
//			}
//
//		}
//
//	}
//
//	if errList.GetErrListAsOne() != nil {
//		return fmt.Errorf("CheckAndReplyV2 err=%v", errList.GetErrListAsOne())
//	}
//
//	return nil
//}

// GetIfReply 检查是否已回复
// 美团只需要第一条消息在一分钟之内回复就达标了,后面不需要自动回复了
func GetIfReply(key string, keyDetail UserRelInfo) (flag bool) {
	flag = false
	if n, err := rdb.Exists(key); n > 0 && err == nil {
		str := rdb.LRange(key)
		for i := 0; i < len(str); i++ {
			v := AutoReply{}
			if err = json.Unmarshal([]byte(str[i]), &v); err == nil {
				flag = v.IsApply
			}
		}
	}

	//检测是否商家回复
	var param []UserRelInfo
	temp := append(param, keyDetail)
	detail, err := GetImChatDetail(temp)
	if err == nil && detail != nil {
		tKey := keyDetail.AppID + ":" + keyDetail.VendorStoreID + ":" + keyDetail.VendorID + ":" + keyDetail.UserID
		if detail[tKey] != nil {
			for _, v := range detail[tKey] {
				b := v.(string)
				lastMsg := &JXMsg{}
				err = json.Unmarshal([]byte(b), lastMsg)
				if err != nil {
					return false
				}
				switch keyDetail.VendorID {
				case utils.Int2Str(model.VendorIDMTWM):
					mt := lastMsg.MsgContent.(map[string]interface{})
					if mt["msg_source"].(float64) == mtwmapi.MsgSourceStore {
						return true
					}
				case utils.Int2Str(model.VendorIDEBAI):
					elm := lastMsg.MsgContent.(map[string]interface{})
					s := ""
					if elm["payLoad"].(map[string]interface{})["senderId"] != nil {
						s = elm["payLoad"].(map[string]interface{})["senderId"].(string)
					}
					if s == "" || s[:2] == ebaiapi.SenderTypeBusiness || s[:2] == ebaiapi.SenderTypeChainedAccountLogin || s[:2] == ebaiapi.SenderTypeSystem {
						return true
					}
				case utils.Int2Str(model.VendorIDJD):
					mt := lastMsg.MsgContent.(map[string]interface{})
					if mt["source"].(string) != "" {
						return true
					}

				}
			}

			//tDetail := detail[tKey][len(detail[tKey])-1]
			//b := tDetail.(string)
			//lastMsg := &JXMsg{}
			//err = json.Unmarshal([]byte(b), lastMsg)
			//if err != nil || lastMsg.SendType == SendTypeJx {
			//	return false
			//}
			//switch keyDetail.VendorID {
			//case VendorIDMTStr:
			//	mt := lastMsg.MsgContent.(map[string]interface{})
			//	if mt["msg_source"].(float64) != mtwmapi.MsgSourceUser {
			//		return false
			//	}
			//case VendorIDELMStr:
			//	elm := lastMsg.MsgContent.(map[string]interface{})
			//	s := elm["payLoad"].(map[string]interface{})["senderId"].(string)
			//	if s == "" || s[:2] != ebaiapi.SenderTypeUser {
			//		return false
			//	}
			//}
		}
	}
	return flag
}

// RecordAutoStatus 记录是否已自动回复状态
func RecordAutoStatus(key string, apply *AutoReply) error {
	data, _ := json.Marshal(apply)
	err := rdb.RPush(key, string(data))
	ok, err := rdb.ExpireResult(key, ExpireTimeAutoReply)
	if err != nil || !ok {
		globals.SugarLogger.Debugf("CheckAndReply apply err:%v", err)
		return err
	}
	return nil
}

// GenCustomReplyID 生成门店自动回复模板ID
func GenCustomReplyID(appID, vendorStoreID string) string {
	return BaseCusKey + ":" + appID + ":" + vendorStoreID
}

// GetCustomTemplate 获取自动回复模板
func GetCustomTemplate(appID, vendorStoreID string) (storeTemplate StoreTemplate) {
	var retVal string
	key := GenCustomReplyID(appID, vendorStoreID)

	data := rdb.LRange(key)
	if data != nil {
		retVal = data[0]
	}

	//temp := rdb.Get(key)
	//temp := regexp.MustCompile(`^"(.*)"$`).ReplaceAllString(retVal, `$1`)
	//storeTemplate = strings.Trim(retVal, "/")
	//fmt.Println(temp)
	temp := StoreTemplate{}
	_ = json.Unmarshal([]byte(retVal), &temp)

	storeTemplate = temp

	return storeTemplate
}

// AddCustomReply 增加门店自定义回复模板
func AddCustomReply(appID, vendorStoreID, replyTemplate string) (storeTemplate string, err error) {
	if len(appID) == 0 || len(vendorStoreID) == 0 {
		return "", errors.New("参数错误请检查！")
	}

	key := GenCustomReplyID(appID, vendorStoreID)

	template := StoreTemplate{
		Template: replyTemplate,
	}
	data, _ := json.Marshal(template)

	err = rdb.Del(key)
	if err == nil && replyTemplate != "" {
		err = rdb.RPush(key, data)
		//err = rdb.Set(key, replyTemplate, 0)
	}
	return "", err
}

// GetDefaultTemplate 获取门店默认回复模板
func GetDefaultTemplate(appID, vendorStoreID string, vendorID int) (string, error) {
	var (
		phoneNum = " "
		t        string
	)
	store, err := dao.GetStoreDetailByVendorStoreID(dao.GetDB(), vendorStoreID, vendorID, "")
	if err != nil {
		return "", err
	}
	if len(store.Tel1) > 0 {
		t = store.Tel1
	}

	phoneNum = t[:3] + "-" + t[3:7] + "-" + t[7:]
	temp := BaseTemplate + phoneNum

	switch vendorID {
	case model.VendorIDMTWM:
		data, err := EncryptIm(utils.Str2Int(appID), temp)
		if err != nil {
			return "", err
		}
		return data, nil
	case model.VendorIDEBAI:
		return temp, nil
	case model.VendorIDJD:
		return temp, nil
	}
	return "", nil
}

/************************工具函数*/

// DelRedisByKey 清除redis数据
func DelRedisByKey(keys []string) {
	var errList errlist.ErrList
	for _, key := range keys {
		err := rdb.Del(key)
		if err != nil {
			errList.AddErr(err)
		}
	}
	if errList.GetErrListAsOne() != nil {
		globals.SugarLogger.Debugf("DelRedisByKey err=%v", errList.GetErrListAsOne())
	}
	return
}

var rel = map[int]string{
	589:  "a81eb3df418d83d6a1a4b7c572156d2f",
	5873: "41c479790a76f86326f89e8048964739",
	4123: "df2c88338b85f830cebce2a9eab56628",
}

// DecryptIm 解密操作
func DecryptIm(appID int, msg string) (string, error) {
	data, _ := base64.StdEncoding.DecodeString(msg)
	key := utils.LimitUTF8StringLen2(rel[appID], 16)
	res, err := utils.AESCBCDecpryt(data, []byte(key), []byte(key))
	if len(string(res)) > 0 && err == nil {
		return string(res), nil
	}
	return "", err
}

// EncryptIm 加密操作
func EncryptIm(appID int, msg string) (retVal string, err error) {
	key := utils.LimitUTF8StringLen2(rel[appID], 16)
	if data, err := utils.AESCBCEncpryt([]byte(msg), []byte(key), []byte(key)); err == nil {
		retVal = base64.StdEncoding.EncodeToString(data)
	}
	return retVal, err
}

// FilterIm 过滤操作
func FilterIm(appID int, msg string) bool {
	var check = "[自动回复]"
	data, _ := DecryptIm(appID, msg)
	if len(data) > 0 && strings.Contains(data, check) {
		return true
	}
	return false
}

// RandTimeNumber   生成int类型 随机数+时间戳
func RandTimeNumber() int {
	num, _ := rand.Int(rand.Reader, big.NewInt(100000))
	str := utils.Int64ToStr(num.Int64()) + utils.Int2Str(int(time.Now().Unix()))
	return utils.Str2Int(str)
}
