package im

import (
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"strings"
	"time"

	"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) {
	if data.VendorID == model.VendorIDMTWM {
		dataStr, _ := json.Marshal(data.Data)
		temp := string(dataStr)
		globals.SugarLogger.Debugf("SendVendorV2 mtwmtemp=%s", temp)
		if _, err = partner.CurAPIManager.GetAPI(model.VendorIDMTWM, vendorOrgCode).(*mtwmapi.API).MsgSend(string(dataStr)); err != nil {
			return err
		}
	}
	if data.VendorID == model.VendorIDEBAI {
		str, _ := json.Marshal(data.Data)
		param := &ebaiapi.BusinessSendMsgReq{}
		err = json.Unmarshal(str, &param)
		globals.SugarLogger.Debugf("SendVendorV2 ebaiparam=%s", utils.Format4Output(param, false))
		err = partner.CurAPIManager.GetAPI(model.VendorIDEBAI, vendorOrgCode).(*ebaiapi.API).BusinessSendMsg(param)
	}
	err = ReadMsgFromClient(data.VendorID, vendorOrgCode, data.Data)
	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:
			temp, err := partner.CurAPIManager.GetAPI(model.VendorIDMTWM, v.VendorOrgCode).(*mtwmapi.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)
		}
	}
	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))
			}
		}
	}
	return errList.GetErrListAsOne()
}

// ReadMsgFromClient 存储客户端发送的消息
func ReadMsgFromClient(vendorID int, elmAppID string, msg interface{}) 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))
	}

	if vendorID == VendorIDMT {
		var pushContent = mtwmapi.PushContentReq{}
		err = json.Unmarshal(data, &pushContent)
		jxMsg = &JXMsg{
			SendType:   SendTypeJx,
			MsgContent: pushContent,
		}
		userList = &UserMessageList{
			VendorID:   VendorIDMT,
			UserID:     utils.Int2Str(pushContent.OpenUserID),
			LatestMsg:  pushContent.MsgContent,
			LatestTime: pushContent.Cts,
			OrderID:    "",
		}
		if pushContent.OrderID != 0 {
			userList.OrderID = utils.Int2Str(pushContent.OrderID)
		}
	}
	if vendorID == VendorIDELM {
		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:   VendorIDELM,
			UserID:     ElmData.PayLoad.GroupID,
			LatestMsg:  ElmData.PayLoad.Content,
			LatestTime: elmTime,
		}
	}

	//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))
	}
	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{}
	)
	if len(string(msg)) == 0 {
		errList.AddErr(fmt.Errorf("读取平台数据为空，请检查"))
	}
	if vendorID == VendorIDMT {
		var PushContentReq = mtwmapi.PushContentReq{}
		err = json.Unmarshal(msg, &PushContentReq)
		if FilterIm(PushContentReq.AppID, PushContentReq.MsgContent) { //自动回复消息过滤
			return nil
		}
		jxMsg = &JXMsg{
			SendType:   SendTypeMt,
			MsgContent: PushContentReq,
		}
		userList = &UserMessageList{
			VendorID:   VendorIDMT,
			UserID:     utils.Int2Str(PushContentReq.OpenUserID),
			LatestMsg:  PushContentReq.MsgContent,
			LatestTime: PushContentReq.Cts,
			OrderID:    "",
		}
		vendorStoreID = PushContentReq.AppPoiCode
		if PushContentReq.OrderID != 0 {
			userList.OrderID = utils.Int2Str(PushContentReq.OrderID)
		}
	}
	if vendorID == VendorIDELM {
		var ElmData = ebaiapi.ImMessageSend{}
		err = json.Unmarshal(msg, &ElmData)
		jxMsg = &JXMsg{
			SendType:   SendTypeElm,
			MsgContent: ElmData,
		}
		userList = &UserMessageList{
			VendorID:   VendorIDELM,
			UserID:     ElmData.PayLoad.GroupID,
			LatestMsg:  ElmData.PayLoad.Content,
			LatestTime: int(ElmData.PayLoad.CreateTime / 1000),
		}
		globals.SugarLogger.Debugf("elm userList=%s", utils.Format4Output(userList, false))

	}

	//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推送新消息
	if err = PushMsgByCid(vendorStoreID, vendorID, string(msg)); err != nil {
		errList.AddErr(fmt.Errorf("向商家cid推送新消息错误：%v", err))
	}

	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 {
	//生成京西消息ID detail
	msgID := GenMsgDetailID(req, vendorID, elmAppID)
	data, _ := json.Marshal(req)
	globals.SugarLogger.Debugf("SetMessageDetail data=%s", string(data))
	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)

	//获取未读消息条数并删除旧数据
	cnt, err := GetNewAndTrim(msgID, userList.UserID)
	if cnt > 0 {
		userList.NewMessageNum = cnt
	} else {
		userList.NewMessageNum = 1
	}
	//存储当前数据
	data, _ := json.Marshal(userList)
	globals.SugarLogger.Debugf("SetUserList data=%s", string(data))
	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 vendorID == VendorIDMT {
		var d1 = jxMsg.MsgContent.(mtwmapi.PushContentReq)
		msgID = utils.Int2Str(d1.AppID) + ":" + d1.AppPoiCode + ":1:" + utils.Int2Str(d1.OpenUserID)
	}
	if vendorID == VendorIDELM {
		var d2 = jxMsg.MsgContent.(ebaiapi.ImMessageSend)
		msgID = elmAppID + ":" + d2.PlatformShopID + ":3:" + d2.PayLoad.GroupID
	}
	return msgID
}

// GenMsgListID 生成展示列表时单条数据ID（部分）
func GenMsgListID(jxMsg *JXMsg, vendorID int, elmAppID string) (msgID string) {
	if vendorID == VendorIDMT {
		var d1 = jxMsg.MsgContent.(mtwmapi.PushContentReq)
		msgID = utils.Int2Str(d1.AppID) + ":" + d1.AppPoiCode + ":1"
	}
	if vendorID == VendorIDELM {
		var d2 = jxMsg.MsgContent.(ebaiapi.ImMessageSend)
		msgID = elmAppID + ":" + d2.PlatformShopID + ":3"
	}
	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
}

// 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
}

// 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
}

// 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
}
