package mtwmapi

import (
	"encoding/json"
	"net/http"
	"net/url"
	"strings"
	"time"

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

const (
	MsgPoiStatusOpened  = 121 // 121=营业
	MsgPoiStatusClosed  = 120 // 120=休息
	MsgPoiStatusOnline  = 18  // 18=上线
	MsgPoiStatusOffline = 19  // 19=下线
)

const (
	MsgTypeWaybillStatus          = "waybillStatus"
	MsgTypeNewOrder               = "newOrder"
	MsgTypeOrderAccepted          = "orderAccepted"
	MsgTypeOrderFinished          = "orderFinished"
	MsgTypeOrderFinancial         = "orderFinancial"
	MsgTypeOrderCanceled          = "orderCanceled"
	MsgTypeUserUrgeOrder          = "userUrgeOrder"
	MsgTypePrivateNumberDowngrade = "numberDowngrade"
	MsgTypeOrderModified          = "orderModified"      // 这个不是订单调整，是订单信息（地址、联系人等）变化后推送的消息
	MsgTypeOrderRefund            = "orderRefund"        // 订单退款(全额)
	MsgTypeOrderPartialRefund     = "orderPartialRefund" // /订单部分退款
	MsgTypeOrderFinishedPickup    = "orderFinishedPickup"
	MsgTypeOrderDeliveryFeeChange = "deliveryFeeChange"

	MsgTypeStoreStatusChanged      = "storeStatusChanged"
	MsgTypeStoreAuditStatusChanged = "storeAuditStatusChanged"
	MsgTypeSkuDelete               = "skuDelete" // 线上商品删除回调
	MsgTypeSkuUpdate               = "skuUpdate" // 线上修改商品回调(非api操作商品回调)
	MsgTypeStoreBind               = "storeBind"

	MsgTypeOrderAgree = "agree" // 同意退款回调
)

type CallbackResponse struct {
	Data string `json:"data"`
}

// 全额退款没有Food, FoodList, Money项
type CallbackRefundInfo struct {
	Timestamp int64  `json:"timestamp"`
	AppID     string `json:"app_id"`
	Sig       string `json:"sig"`

	OrderID     int64              `json:"order_id"`
	NotifyType  string             `json:"notify_type"`
	RefundID    int64              `json:"refund_id"`
	Ctime       int64              `json:"ctime"`
	Reason      string             `json:"reason"`
	ResType     int                `json:"res_type"`
	IsAppeal    int                `json:"is_appeal"`
	Pictures    string             `json:"pictures"`
	PictureList []string           `json:"pictureList"`
	Status      string             `json:"status"`
	Food        string             `json:"food"`
	FoodList    []*RefundSkuDetail `json:"foodList"`
	Money       float32            `json:"money"`
}

type CallbackMsg struct {
	Cmd string

	Timestamp int64  `json:"timestamp"`
	AppID     string `json:"app_id"`
	Sig       string `json:"sig"`

	FormData url.Values
	Data     interface{}
}

var (
	SuccessResponse  = &CallbackResponse{Data: "ok"}
	SignatureIsNotOk = &CallbackResponse{Data: "sign failed"}
)

func Err2CallbackResponse(err error, data string) *CallbackResponse {
	if err == nil {
		return SuccessResponse
	}
	if data == "" {
		data = err.Error()
	}
	return &CallbackResponse{
		Data: data,
	}
}

func (a *API) GetCallbackMsg(request *http.Request) (msg *CallbackMsg, callbackResponse *CallbackResponse) {
	err := request.ParseForm()
	if err == nil {
		data := utils.URLValues2Map(request.Form)
		if dataSign, ok := data[signKey]; ok {
			// fullURL := strings.TrimRight(a.callbackURL+request.URL.Path, "/")
			// sign := a.signParams(fullURL+"?", data)
			cmd := strings.Trim(request.URL.EscapedPath(), "/")
			cmd = cmd[strings.LastIndex(cmd, "/")+1:]
			// if sign != dataSign.(string) && cmd != MsgTypeStoreStatusChanged {
			// 	callbackResponse = SignatureIsNotOk
			// } else {
			msg = &CallbackMsg{
				Cmd: cmd,
			}
			msg.FormData = make(url.Values)
			for k, v := range data {
				// 美团外卖的用户催单信息的timestamp是毫秒（其它的事件是秒），统一归一化为秒
				if cmd == MsgTypeUserUrgeOrder && k == "timestamp" {
					intV := utils.Str2Int64(v.(string))
					if intV > time.Now().Unix()*2 {
						v = utils.Int64ToStr(intV / 1000)
						data[k] = v
					}
				}
				msg.FormData.Set(k, v.(string))
			}
			msg.Timestamp = utils.Str2Int64(msg.FormData.Get("timestamp"))
			msg.Sig = dataSign.(string)
			msg.AppID = msg.FormData.Get("app_id")

			if msg.Cmd == MsgTypeOrderRefund || msg.Cmd == MsgTypeOrderPartialRefund {
				var refundData *CallbackRefundInfo
				if err = utils.Map2StructByJson(data, &refundData, true); err == nil {
					if refundData.Food != "" {
						utils.UnmarshalUseNumber([]byte(refundData.Food), &refundData.FoodList)
					}
					if refundData.Pictures != "" {
						utils.UnmarshalUseNumber([]byte(refundData.Pictures), &refundData.PictureList)
					}
					msg.Data = refundData
				}
			}
			// }
		} else {
			callbackResponse = SuccessResponse // 美团外卖PING消息没有sign
		}
	} else {
		baseapi.SugarLogger.Warnf("mtwm GetCallbackMsg ParseForm failed with error:%v", err)
		callbackResponse = Err2CallbackResponse(err, "")
	}
	return msg, callbackResponse
}

func (a *API) GetRefundSkuDetailFromMsg(msg *CallbackMsg) (refundSkuDetail []*RefundSkuDetail) {
	utils.UnmarshalUseNumber([]byte(msg.FormData.Get("food")), &refundSkuDetail)
	return refundSkuDetail
}

// 单独处理im回调
func (a *API) GetIMCallbackMsg(request *http.Request) (msg *ImCallbackMsg, callbackResponse *CallbackResponse) {
	var (
		err         = request.ParseForm()
		pushContent PushContentReq
		tData       string
	)
	msg = &ImCallbackMsg{}
	msg.FormData = make(url.Values)
	if err == nil {
		data := utils.URLValues2Map(request.Form)
		if dataSign, ok := data[signKey]; ok {
			for k, v := range data {
				if k == "push_content" {
					//tData, _ = json.Marshal(v)
					tData = v.(string)
					continue
				}
				msg.FormData.Set(k, v.(string))
			}
			msg.Timestamp = utils.Str2Int(msg.FormData.Get("timestamp"))
			msg.Sig = dataSign.(string)
			msg.AppID = msg.FormData.Get("app_id")
			if err = json.Unmarshal([]byte(tData), &pushContent); err == nil {
				msg.PushContent = pushContent
			}
			//if err = utils.Map2StructByJson(tData, &pushContent, true); err == nil {
			//	msg.PushContent = pushContent
			//}
		} else {
			callbackResponse = SuccessResponse
		}
	} else {
		baseapi.SugarLogger.Warnf("mtwm GetCallbackMsg ParseForm failed with error:%v", err)
		callbackResponse = Err2CallbackResponse(err, "")
	}
	return msg, callbackResponse
}

// 平台修改商品消息通知(目前只接收上下架状态)
type VendorUpdateSkuCallback struct {
	AppFoodCode  string `json:"app_food_code"`
	AppId        int    `json:"app_id"`
	AppPoiCode   string `json:"app_poi_code"`
	AppSpuCode   string `json:"app_spu_code"`
	CategoryName string `json:"categoryName"`
	Ctime        int    `json:"ctime"`
	DiffContents struct {
		Skus []struct {
			Desc           string `json:"desc"`
			DiffContentMap struct {
				SkuIsSoldOut struct {
					Result int `json:"result"`
					Origin int `json:"origin"`
				} `json:"sku_is_sold_out"`
			} `json:"diffContentMap"`
			Id          string `json:"id"`
			OpType      int    `json:"opType"`
			OtherExtend struct {
			} `json:"otherExtend"`
		} `json:"skus"`
		IsSoldOut struct {
			Result int `json:"result"`
			Origin int `json:"origin"`
		} `json:"is_sold_out"`
	} `json:"diffContents"`
	Name      string `json:"name"`
	OpAppKey  string `json:"opAppKey"`
	OpName    string `json:"opName"`
	OpReason  string `json:"opReason"`
	Timestamp int    `json:"timestamp"`
	Utime     int    `json:"utime"`
}
