package dadaapi

import (
	"crypto/md5"
	"fmt"
	"sort"
	"strings"

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

const (
	ResponseHttpCodeSuccess    = 200
	ResponseHttpCodeGeneralErr = 555
)

type CallbackMsg struct {
	ClientID     string `json:"client_id"`
	OrderID      string `json:"order_id"`
	OrderStatus  int    `json:"order_status"`
	CancelReason string `json:"cancel_reason"`
	CancelFrom   int    `json:"cancel_from"`
	UpdateTime   int    `json:"update_time"`
	Signature    string `json:"signature"`
	DmID         int    `json:"dm_id"`
	DmName       string `json:"dm_name"`
	DmMobile     string `json:"dm_mobile"`
}

type CallbackResponse struct {
	Code  int    `json:"code"` // 对于达达是无意义的，只是用于传递相应的HTTP CODE
	Dummy string `json:"dummy"`
}

var (
	SuccessResponse = &CallbackResponse{Code: ResponseHttpCodeSuccess}
	FailedResponse  = &CallbackResponse{Code: ResponseHttpCodeGeneralErr}
)

func Err2CallbackResponse(err error, data string) *CallbackResponse {
	if err == nil {
		return SuccessResponse
	}
	return FailedResponse
}

func (a *API) signCallbackParams(mapData map[string]interface{}) string {
	values := make([]string, 0)
	for _, k := range []string{"client_id", "order_id", "update_time"} {
		values = append(values, fmt.Sprint(mapData[k]))
	}
	sort.Strings(values)

	finalStr := strings.Join(values, "")
	return fmt.Sprintf("%x", md5.Sum([]byte(finalStr)))
}

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

func (a *API) CheckCallbackValidation(mapData map[string]interface{}) (callbackResponse *CallbackResponse) {
	sign := a.signCallbackParams(mapData)
	if remoteSign, _ := mapData[signKey].(string); sign != remoteSign {
		return FailedResponse
	}
	return nil
}

func (a *API) GetOrderCallbackMsg(data []byte) (msg *CallbackMsg, callbackResponse *CallbackResponse) {
	msg = new(CallbackMsg)
	if callbackResponse = a.unmarshalData(data, msg); callbackResponse != nil {
		return nil, FailedResponse
	}

	mapData := utils.Struct2MapByJson(msg)
	callbackResponse = a.CheckCallbackValidation(mapData)
	return msg, callbackResponse
}
