package ebaiapi

import (
	"errors"
	"fmt"
	"git.rosy.net.cn/baseapi"
	"git.rosy.net.cn/baseapi/utils"
	"net/http"
	"net/url"
)

const (
	CmdOrderCreate         = "order.create"
	CmdOrderDeliveryStatus = "order.deliveryStatus.push"
	CmdOrderPartRefund     = "order.partrefund.push" // 售前只能是商户发起 售后是用户, 你看是由谁发起的就可以知道，来自惠焕(部分退款,饿百废弃了)
	CmdOrderReversePush    = "order.reverse.push"    // 订单逆向消息推送
	CmdOrderStatus         = "order.status.push"
	CmdOrderUserCancel     = "order.user.cancel"

	CmdShopMsgPush   = "shop.msg.push"
	CmdShopBindMsg   = "shop.bind.msg"
	CmdShopUnbindMsg = "shop.unbind.msg"

	//IM消息回调通知
	CmdImMessageSendEvent = "im.message.send.event" // 用户/骑手消息通知
	CmdImMessageReadEvent = "im.message.read.event" // 用户/骑手已读通知
	CmdImInvoicApply      = "invoice.apply.push"    // 用户发送发票申请
	CmdImInvoicEmail      = "invoice.email.push"    // 发票用户重发邮件

)

type CallbackResponse struct {
	Cmd       string          `json:"cmd"`
	Sign      string          `json:"sign"`
	Source    string          `json:"source"`
	Ticket    string          `json:"ticket"`
	Encrypt   string          `json:"encrypt"`
	Timestamp int64           `json:"timestamp"`
	Version   int             `json:"version"`
	Body      *ResponseResult `json:"body"`
}

type CallbackMsg struct {
	Cmd       string `json:"cmd"`
	Version   string `json:"version"`
	Timestamp int64  `json:"timestamp"`
	Ticket    string `json:"ticket"`
	Source    string `json:"source"`
	Sign      string `json:"sign"`
	Encrypt   string `json:"encrypt"`

	Body map[string]interface{} `json:"body"`
	Data interface{}            `json:"data"`
}

type EBaiShopList struct {
	BaiduShopID string `json:"baidu_shop_id"`
	ShopID      string `json:"shop_id"`
	Name        string `json:"name"`
	Source      string `json:"source"`
	SupplierID  string `json:"supplier_id"`
}

type CBPartRefundInfo struct {
	OrderID        int64    `json:"order_id"`
	RefundID       string   `json:"refund_id"`
	Type           int      `json:"type"`
	Status         int      `json:"status"`
	AdditionReason string   `json:"addition_reason"`
	Photos         []string `json:"photos"`
	ReasonType     string   `json:"reason_type"`
	Reason         string   `json:"reason"`
	RefundProducts []*struct {
		SkuID         string `json:"sku_id"`
		Upc           string `json:"upc"`
		CustomSkuID   string `json:"custom_sku_id"`
		Name          string `json:"name"`
		Number        int    `json:"number"`
		TotalRefund   int64  `json:"total_refund"`
		ShopEleRefund int64  `json:"shop_ele_refund"`
	} `json:"refund_products"`
	RefundPrice int64 `json:"refund_price"`
}

type CBOrderReversePush struct {
	EventId         string `json:"event_id"`         // 操作事件全局唯一事件
	PlatformShopId  int    `json:"platform_shop_id"` // 平台门店ID
	OrderId         string `json:"order_id"`         // 订单ID
	RefundOrderId   int64  `json:"refund_order_id"`  // 逆向单号
	CurReverseEvent struct {
		EventId               string   `json:"event_id"`                 // 操作事件全局唯一事件
		ImageList             []string `json:"image_list"`               // 操作凭证列表
		LastRefundStatus      int      `json:"last_refund_status"`       // 逆向单操作前的退货状态：0-无效状态，1001-买家已申请退货，等待审批处理，1002-商家拒绝退货申请，1003-退货仲裁已发起，客服介入中，1004-已同意退货，等待发货，1005-已发货，等待卖家确认收货，1006-已收到货，并同意退款， 1007-未收到货，不同意退款，1008-退货关闭
		LastReturnGoodsStatus int      `json:"last_return_goods_status"` // 逆向单操作前的逆向单状态：0-初始化，10-申请，20-拒绝，30-仲裁，40-关闭，50-成功，60-失败
		OccurTime             int64    `json:"occur_time"`               // 逆向单操作事件发生时间 单位：毫秒
		OperatorRole          int      `json:"operator_role"`            // 逆向单操作者角色：10 用户 ,20商户,30客服 ,25 API商家代客发起,40系统
		OrderId               string   `json:"order_id"`                 // 订单ID
		ReasonCode            int      `json:"reason_code"`              // 逆向单操作原因对应code，具体原因枚举详见文档https://open-retail.ele.me/#/guide?topic=ntmt8f
		ReasonContent         string   `json:"reason_content"`           // 逆向单操作原因备注内容
		RefundOrderId         int64    `json:"refund_order_id"`          // 逆向单号
		RefundReasonDesc      string   `json:"refund_reason_desc"`       // 逆向单操作原因code对应的文案
		RefundStatus          int      `json:"refund_status"`            // 即当前的逆向单状态：0-初始化，10-申请，20-拒绝，30-仲裁，40-关闭，50-成功，60-失败
		ReturnGoodsStatus     int      `json:"return_goods_status"`      // 即当前的退货状态）：0-无效状态，1001-买家已申请退货，等待审批处理，1002-商家拒绝退货申请，1003-退货仲裁已发起，客服介入中，1004-已同意退货，等待发货，1005-已发货，等待卖家确认收货，1006-已收到货，并同意退款， 1007-未收到货，不同意退款，1008-退货关闭
	} `json:"cur_reverse_event"` // 逆向单当前操作信息
}

type CBUserCancelInfo struct {
	OrderID        int64    `json:"order_id"`
	CancelReason   string   `json:"cancel_reason"`
	AdditionReason string   `json:"addition_reason"`
	RefuseReason   string   `json:"refuse_reason"`
	Pictures       []string `json:"pictures"`
	Type           int      `json:"type"`
	CancelType     int      `json:"cancel_type"`
	ReasonCodeDesc string   `json:"reason_code_desc"`
	PlatformShopId int      `json:"platform_shop_id"`
	ReasonCode     int      `json:"reason_code"`
	RefundOrderId  string   `json:"refund_order_id"`
	IsReturnGoods  string   `json:"is_return_goods"`
}

//temp IM 用户/骑手消息通知
type TempSent struct {
	SubBizType string `json:"subBizType"` //业务子类型，枚举值：SEND_MESSAGE-发送消息
	BizType    string `json:"bizType"`    //业务类型，枚举值：IM-消息
	PayLoad    struct {
		SenderID    string   `json:"senderId"`    //角色+随机数字串；角色：10(用户)、20(骑手)、30(商家)、32（连锁账号登录）
		ReceiverIDs []string `json:"receiverIds"` //角色+随机数字串；角色：10(用户)、20(骑手)、30(商家)、32（连锁账号登录）
		CreateTime  int64    `json:"createTime"`  //时间戳
		GroupID     string   `json:"groupId"`     //会话id
		MsgID       string   `json:"msgId"`       //消息ID
		ContentType int      `json:"contentType"` //消息类型，枚举值：1-普通文本
	} `json:"payload"`
	PlatformShopID string `json:"platformShopId"` //平台门店ID
}

//IM 用户/骑手消息通知
type ImMessageSend struct {
	SubBizType     string  `json:"subBizType"` //业务子类型，枚举值：SEND_MESSAGE-发送消息
	BizType        string  `json:"bizType"`    //业务类型，枚举值：IM-消息
	PayLoad        PayLoad `json:"payLoad"`
	PlatformShopID string  `json:"platformShopId"` //平台门店ID
}
type PayLoad struct {
	SenderID    string   `json:"senderId"`    //角色+随机数字串；角色：10(用户)、20(骑手)、30(商家)、32（连锁账号登录）
	ReceiverIDs []string `json:"receiverIds"` //角色+随机数字串；角色：10(用户)、20(骑手)、30(商家)、32（连锁账号登录）
	CreateTime  int      `json:"createTime"`  //时间戳
	GroupID     string   `json:"groupId"`     //会话id
	MsgID       string   `json:"msgId"`       //消息ID
	ContentType string   `json:"contentType"` //消息类型，枚举值：1-普通文本
	Content     string   `json:"content"`
}

//ContentType =1-普通文本,8-@消息
type Content struct {
	Text string `json:"text"`
}

//IM 用户/骑手已读通知
type ImMessageRead struct {
	PlatformShopID string `json:"platformShopId"` //平台门店ID
	BizType        string `json:"bizType"`        //业务类型，枚举值：IM-消息
	SubBizType     string `json:"subBizType"`     //业务子类型，枚举值：READ_MESSAGE-读取消息
	PayLoad        struct {
		MsgIDs string `json:"msgIds"` //消息ID 列表
		CID    string `json:"cid"`    //会话id
		UID    string `json:"uid"`    //已读操作人
	} `json:"payLoad"`
}

func (a *API) Err2CallbackResponse(cmd string, err error, data interface{}) *CallbackResponse {
	response := &CallbackResponse{
		Cmd:       "resp." + cmd,
		Source:    a.source,
		Ticket:    utils.GetUpperUUID(),
		Timestamp: utils.GetCurTimestamp(),
		Version:   3,
	}
	if err == nil {
		response.Body = &ResponseResult{
			Error: "success",
			ErrNo: 0,
			Data:  data,
		}
	} else {
		response.Body = &ResponseResult{
			Error: fmt.Sprintf("error:%v, data:%v", err, data),
			ErrNo: -1,
			Data:  data,
		}
	}
	params := url.Values{
		"cmd":       []string{response.Cmd},
		"version":   []string{utils.Int2Str(response.Version)},
		"timestamp": []string{utils.Int64ToStr(response.Timestamp)},
		"ticket":    []string{response.Ticket},
		"source":    []string{response.Source},
		"body":      []string{string(utils.MustMarshal(response.Body))},
		"encrypt":   []string{""},
	}
	response.Sign = a.signParams(params)
	return response
}

func (a *API) unmarshalData(cmd string, data []byte, msg interface{}) (callbackResponse *CallbackResponse) {
	err := utils.UnmarshalUseNumber(data, msg)
	if err != nil {
		return a.Err2CallbackResponse(cmd, err, nil)
	}
	return nil
}

func (a *API) CheckCallbackValidation(cmd string, params url.Values) (callbackResponse *CallbackResponse) {
	sign := a.signParams(params)
	if sign != params.Get(signKey) {
		msg := fmt.Sprintf("Signature is not ok, mine:%v, get:%v", sign, params.Get(signKey))
		baseapi.SugarLogger.Info(msg)
		return a.Err2CallbackResponse(cmd, errors.New(msg), nil)
	}
	return nil
}

func (a *API) GetCallbackMsg(request *http.Request, runModel string) (msg *CallbackMsg, callbackResponse *CallbackResponse) {
	err := request.ParseForm()
	if err == nil {
		params := make(url.Values)
		for k := range request.PostForm {
			decodedValue, _ := url.QueryUnescape(request.PostFormValue(k))
			params.Set(k, decodedValue)
		}
		msg = new(CallbackMsg)
		msg.Cmd = GetCmd(request)
		if runModel == "prod" {
			if callbackResponse = a.CheckCallbackValidation(msg.Cmd, params); callbackResponse != nil {
				return nil, callbackResponse
			}
		}

		if callbackResponse = a.unmarshalData(msg.Cmd, []byte(params.Get("body")), &msg.Body); callbackResponse != nil {
			return nil, callbackResponse
		}
		msg.Timestamp = utils.Str2Int64(params.Get("timestamp"))
		msg.Version = params.Get("version")
		msg.Ticket = params.Get("ticket")
		msg.Source = params.Get("source")
		msg.Sign = params.Get("sign")
		msg.Encrypt = params.Get("encrypt")

		var tmpObj interface{}
		switch msg.Cmd {
		case CmdOrderPartRefund:
			var partRefundData CBPartRefundInfo
			tmpObj = &partRefundData
		case CmdOrderUserCancel:
			var userCancelData CBUserCancelInfo
			tmpObj = &userCancelData
		case CmdImMessageSendEvent:
			tmpObj = &ImMessageSend{}
		case CmdImMessageReadEvent:
			tmpObj = &ImMessageRead{}
		case CmdOrderReversePush:
			var reversePush CBOrderReversePush
			tmpObj = &reversePush
		}
		if tmpObj != nil {
			if utils.Map2StructByJson(msg.Body, tmpObj, true) == nil {
				msg.Data = tmpObj
			}
		}
		return msg, nil
	}
	return nil, a.Err2CallbackResponse("", err, nil)
}

func GetCmd(request *http.Request) (cmd string) {
	cmd, _ = url.QueryUnescape(request.FormValue("cmd"))
	return cmd
}
