package kuaishou_mini

import (
	"encoding/json"
	"errors"
	"fmt"
	"git.rosy.net.cn/baseapi/utils"
	"time"
)

// PreCreateOrder 预下单生成支付信息
func (a *API) PreCreateOrder(param *PreCreateOrderReq) (*CreateOrderResponseInfo, error) {
	if a.appId == "" || a.appSecret == "" {
		return nil, errors.New("appId/appSecret 不能为空")
	}

	param.Sign = a.sign(utils.Struct2MapByJson(param))
	result, err := a.AccessAPI1(a.FullUrl(KuaiShouPreCreateOrder), utils.Struct2MapByJson(param))
	if err != nil {
		return nil, err
	}
	order := PreCreateOrderResponse{}
	if err := utils.Map2StructByJson(result, &order, false); err != nil {
		return nil, err
	}

	if order.Result != 1 {
		return nil, errors.New(order.ErrorMsg)
	}

	return &order.OrderInfo, nil
}

// GetOrderDetail 订单详情查询接口
func (a *API) GetOrderDetail(outOrderNo string) (*PaymentInfo, error) {
	if a.appId == "" || a.appSecret == "" {
		return nil, errors.New("appId/appSecret 不能为空")
	}

	sign := a.sign(map[string]interface{}{"out_order_no": outOrderNo})
	data, err := a.AccessAPI1(a.FullUrl(KuaiShouGetOrderDetail), map[string]interface{}{"out_order_no": outOrderNo, "sign": sign})
	if err != nil {
		return nil, err
	}

	orderDetail := &GetOrderDetailRes{}
	if err := utils.Map2StructByJson(data, orderDetail, false); err != nil {
		return nil, err
	}

	if orderDetail.Result != 1 {
		return nil, err
	}

	if orderDetail.PaymentInfo == "" {
		return nil, errors.New("快手支付订单详情返回值为空")
	}

	paymentInfo := &PaymentInfo{}
	if err := json.Unmarshal([]byte(orderDetail.PaymentInfo), paymentInfo); err != nil {
		return nil, err
	}

	return paymentInfo, err
}

// RefundOrder 支付请求退款接口
// 在途资金中的所有货款均是与订单关联的，只有当该订单在途资金中剩余金额超过退款金额时，才可以进行在途资金的退款。
// 当可提现金额也不足退款金额时，会退款失败，为了避免出现订单无法退款的情况出现，请根据业务情况自行保留一部分可提现金额在系统中
func (a *API) RefundOrder(param *RefundParam) (refundNo string, err error) {
	if a.appId == "" || a.appSecret == "" {
		return "", errors.New("appId/appSecret 不能为空")
	}

	param.Sign = a.sign(utils.Struct2MapByJson(param))

	data, err := a.AccessAPI1(a.FullUrl(KuaiShouRefundOrder), utils.Struct2MapByJson(param))
	if err != nil {
		return "", err
	}

	var result *RefundRes
	if err := utils.Map2StructByJson(data, &result, false); err != nil {
		return "", err
	}

	if result.Result != 1 {
		return "", errors.New(result.ErrorMsg)
	}
	return result.RefundNo, nil
}

// RefundOrderDetail 查询退款订单详情
func (a *API) RefundOrderDetail(outRefundNo string) (*RefundInfo, error) {
	if a.appId == "" || a.appSecret == "" {
		return nil, errors.New("appId/appSecret 不能为空")
	}

	sign := a.sign(map[string]interface{}{"out_refund_no": outRefundNo})

	data, err := a.AccessAPI1(a.FullUrl(KuaiShouRefundOrderDetail), map[string]interface{}{"out_refund_no": outRefundNo, "sign": sign})
	if err != nil {
		return nil, err
	}

	var refundOrderDetail *RefundOrderDetail
	if err := utils.Map2StructByJson(data, &refundOrderDetail, false); err != nil {
		return nil, err
	}

	if refundOrderDetail.Result != 1 {
		return nil, errors.New(refundOrderDetail.ErrorMsg)
	}

	var refundInfo *RefundInfo
	if err := json.Unmarshal([]byte(refundOrderDetail.RefundInfo), &refundInfo); err != nil {
		return nil, err
	}

	return refundInfo, nil
}

// PaySettleAccounts 结算用于确认一笔在途资金，将其转化为可提现资金。
// 结算规则
// 1、订单履约完成后发起结算，结算周期为 订单到达核销状态（订单状态为11或15）满3天后可发起结算。核销状态通过订单同步接口 (opens new window)进行同步。
// 2、需要主动调用结算接口后，才能进行后续资金的提现。
// 3、结算时，小程序平台会收取整笔交易的平台服务费。若结算后发生退款，则平台服务费不作退还。

func (a *API) PaySettleAccounts4Order(param *OrderSettleAccountParam) (string, error) {
	if a.appId == "" || a.appSecret == "" {
		return "", errors.New("appId/appSecret 不能为空")
	}

	param.Sign = a.sign(utils.Struct2MapByJson(param))

	data, err := a.AccessAPI1(a.FullUrl(KuaiShouGetSettleOrder), utils.Struct2MapByJson(param))
	if err != nil {
		return "", err
	}

	var settle *OrderSettleAccountRes
	if err := utils.Map2StructByJson(data, &settle, false); err != nil {
		return "", err
	}

	if settle.Result != 1 {
		return "", err
	}

	return settle.SettleNo, nil
}

// QuerySettleInfo 查询结算信息
func (a *API) QuerySettleInfo(outSettleNo string) (*SettleInfo, error) {
	if a.appId == "" || a.appSecret == "" {
		return nil, errors.New("appId/appSecret 不能为空")
	}

	sign := a.sign(map[string]interface{}{"out_settle_no": outSettleNo})

	data, err := a.AccessAPI1(a.FullUrl(KuaiShouQuerySettleOrder), map[string]interface{}{"out_settle_no": outSettleNo, "sign": sign})
	if err != nil {
		return nil, err
	}
	var settle *QuerySettleInfoRes
	if err := utils.Map2StructByJson(data, &settle, false); err != nil {
		return nil, err
	}
	if settle.Result != 1 {
		return nil, errors.New(settle.ErrorMsg)
	}

	if settle.SettleInfo == "" {
		return nil, errors.New("数据查询为空")
	}

	var result *SettleInfo
	if err := json.Unmarshal([]byte(settle.SettleInfo), result); err != nil {
		return nil, err
	}
	return result, err
}

func (a *API) FullUrl(bashUrl string) string {
	if a.accessToken == "" || a.expiresIn < time.Now().Unix() {
		a.GetToken()
	}
	return fmt.Sprintf(bashUrl+"?app_id=%s&access_token=%s", a.appId, a.accessToken)
}
