package lakala

import (
	"encoding/json"
	"errors"
	"fmt"
	"git.rosy.net.cn/baseapi/utils"
	"git.rosy.net.cn/jx-callback/globals"
	"net/http"
	"time"
)

// CreateSeparate 进件成功的门店创建分账
func (a *API) CreateSeparate(param *CreateSeparateReq) (string, error) {
	if (param.SplitLaunchMode == SplitLaunchModeAuto || param.SplitLaunchMode == SplitLaunchModePointRule) && param.SplitRuleSource == "" {
		return "", fmt.Errorf("当分账发起方式为%s/%s时,分账规则来源不能为空", SplitLaunchModeAuto, SplitLaunchModePointRule)
	}
	reqParameter := map[string]interface{}{
		"reqData": utils.Struct2Map(param, "", false),
		"reqId":   param.OrderNo,
		"version": Version,
		"reqTime": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
	}
	result, err := a.AccessAPISign(SeparateAccountProdUrl, SeparateAccountApplyAction, http.MethodPost, "", reqParameter)
	if err != nil {
		return "", err
	}

	bodyResult, err := json.Marshal(result)
	if err != nil {
		return "", err
	}

	resp := &CreateSeparateResp{}
	if err = json.Unmarshal(bodyResult, resp); err != nil {
		return "", err
	}
	if resp.RetCode != Success {
		return "", fmt.Errorf(resp.RetMsg)
	}

	return utils.Int64ToStr(resp.RespData.ApplyId), nil
}

// SeparateModify 商户申请变更分账商户
func (a *API) SeparateModify(modify *SeparateModifyReq) (string, error) {
	if modify.MerInnerNo == "" && modify.MerCupNo == "" {
		return "", fmt.Errorf("k卡拉卡内部账号或银联账号不能同时为空")
	}
	reqParameter := map[string]interface{}{
		"reqData": utils.Struct2Map(modify, "", false),
		"reqId":   modify.OrderNo,
		"version": Version,
		"reqTime": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
	}
	result, err := a.AccessAPISign(SeparateAccountProdUrl, SeparateAccountModifyAction, http.MethodPost, "", reqParameter)
	if err != nil {
		return "", err
	}

	bodyResult, err := json.Marshal(result)
	if err != nil {
		return "", err
	}

	resp := &CreateSeparateResp{}
	if err = json.Unmarshal(bodyResult, resp); err != nil {
		return "", err
	}
	if resp.RetCode != Success {
		return "", fmt.Errorf(resp.RetMsg)
	}

	return utils.Int64ToStr(resp.RespData.ApplyId), nil
}

// SeparateQuery 商户分账信息查询
func (a *API) SeparateQuery(query *SeparateQueryReq) (*SeparateQueryResp, error) {
	if query.MerInnerNo == "" && query.MerCupNo == "" {
		return nil, fmt.Errorf("卡卡拉卡内部账号或银联账号不能同时为空")
	}
	reqParameter := map[string]interface{}{
		"reqData": utils.Struct2Map(query, "", false),
		"reqId":   query.OrderNo,
		"version": Version,
		"reqTime": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
	}
	result, err := a.AccessAPISign(SeparateAccountProdUrl, SeparateAccountQueryAction, http.MethodPost, "", reqParameter)
	if err != nil {
		return nil, err
	}

	if result["retCode"].(string) != Success {
		return nil, fmt.Errorf(result["retMsg"].(string))
	}
	bodyResult, err := json.Marshal(result["respData"])
	if err != nil {
		return nil, err
	}

	resp := &SeparateQueryResp{}
	if err = json.Unmarshal(bodyResult, resp); err != nil {
		return nil, err
	}

	return resp, nil
}

// CreateSeparateRecipient 创建分账接收方
func (a *API) CreateSeparateRecipient(recipient *CreateSeparateRecipientReq) (string, error) {
	switch recipient.AcctTypeCode {
	case BankTypeEnterprise:
		if recipient.AcctNo == "" {
			return "", fmt.Errorf("收款账户账户类型为对公，必须上送[营业执照编号]")
		}
		if recipient.LicenseName == "" {
			return "", fmt.Errorf("收款账户账户类型为对公，必须上送[营业执照名称]")
		}
		if recipient.LegalPersonName == "" {
			return "", fmt.Errorf("收款账户账户类型为对公，必须上送[法人姓名]")
		}
		if recipient.LegalPersonCertificateType == "" {
			return "", fmt.Errorf("收款账户账户类型为对公，必须上送[法人证件类型]")
		}
		if recipient.LegalPersonCertificateNo == "" {
			return "", fmt.Errorf("收款账户账户类型为对公，必须上送[法人证件号]")
		}
	default:

	}

	reqParameter := map[string]interface{}{
		"reqData": utils.Struct2Map(recipient, "", false),
		"reqId":   recipient.OrderNo,
		"version": Version,
		"reqTime": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
	}
	result, err := a.AccessAPISign(SeparateAccountProdUrl, SeparateReceiverApplyAction, http.MethodPost, "", reqParameter)
	if err != nil {
		return "", err
	}

	bodyResult, err := json.Marshal(result)
	if err != nil {
		return "", err
	}

	resp := &CreateSeparateRecipientResp{}
	if err = json.Unmarshal(bodyResult, resp); err != nil {
		return "", err
	}
	if resp.RetCode != Success {
		return "", fmt.Errorf(resp.RetMsg)
	}

	return resp.RespData.ReceiverNo, nil
}

// UpdateSeparateRecipient 分账接收方变更申请
func (a *API) UpdateSeparateRecipient(param *UpdateSeparateRecipientReq) (string, error) {
	if param.ReceiverNo == "" {
		return "", fmt.Errorf("分账接收方编号不能为空")
	}

	reqParameter := map[string]interface{}{
		"reqData": utils.Struct2Map(param, "", false),
		"reqId":   param.OrderNo,
		"version": Version,
		"reqTime": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
	}
	result, err := a.AccessAPISign(SeparateAccountProdUrl, SeparateReceiverModifyAction, http.MethodPost, "", reqParameter)
	if err != nil {
		return "", err
	}

	bodyResult, err := json.Marshal(result)
	if err != nil {
		return "", err
	}

	resp := &CreateSeparateRecipientResp{}
	if err = json.Unmarshal(bodyResult, resp); err != nil {
		return "", err
	}
	if resp.RetCode != Success {
		return "", fmt.Errorf(resp.RetMsg)
	}

	return resp.RespData.OrderNo, nil

}

// QuerySeparateRecipient 分账方详细信息查询
func (a *API) QuerySeparateRecipient(orderNo, receiverNo string) (*QuerySeparateRecipientResp, error) {
	reqParameter := map[string]interface{}{
		"reqData": map[string]string{
			"version":    Version,
			"orderNo":    orderNo,
			"orgCode":    a.orgCode,
			"receiverNo": receiverNo,
		},
	}
	result, err := a.AccessAPISign(SeparateAccountProdUrl, SeparateReceiverQueryAction, http.MethodPost, "", reqParameter)
	if err != nil {
		return nil, err
	}

	if result["retCode"] != Success {
		return nil, errors.New(result["retMsg"].(string))
	}

	bodyResult, err := json.Marshal(result["respData"])
	if err != nil {
		return nil, err
	}

	resp := &QuerySeparateRecipientResp{}
	if err = json.Unmarshal(bodyResult, resp); err != nil {
		return nil, err
	}

	return resp, nil
}

// ApplyBind 申请绑定分账关系
func (a *API) ApplyBind(param *SeparateApplyBindReq) (*SeparateApplyBindResp, error) {
	reqParameter := map[string]interface{}{
		"reqData": utils.Struct2Map(param, "", false),
		"reqId":   param.OrderNo,
		"version": Version,
		"reqTime": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
	}
	result, err := a.AccessAPISign(SeparateAccountProdUrl, SeparateBindAction, http.MethodPost, "", reqParameter)
	if err != nil {
		return nil, err
	}

	bodyResult, err := json.Marshal(result)
	if err != nil {
		return nil, err
	}

	resp := &SeparateApplyBindResp{}
	if err = json.Unmarshal(bodyResult, resp); err != nil {
		return nil, err
	}
	if resp.RetCode != Success {
		return nil, fmt.Errorf(resp.RetMsg)
	}

	return resp, nil
}

// SeparateUnBind 申请解除绑定
func (a *API) SeparateUnBind(param *SeparateUnBindReq) (string, error) {
	reqParameter := map[string]interface{}{
		"reqData": utils.Struct2Map(param, "", false),
		"reqId":   param.OrderNo,
		"version": Version,
		"reqTime": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
	}
	result, err := a.AccessAPISign(SeparateAccountProdUrl, SeparateUnBindAction, http.MethodPost, "", reqParameter)
	if err != nil {
		return "", err
	}

	bodyResult, err := json.Marshal(result)
	if err != nil {
		return "", err
	}

	resp := &SeparateApplyBindResp{}
	if err = json.Unmarshal(bodyResult, resp); err != nil {
		return "", err
	}
	if resp.RetCode != Success {
		return "", fmt.Errorf(resp.RetMsg)
	}

	return utils.Int64ToStr(resp.RespData.ApplyId), nil

}

// Separate 分账
func (a *API) Separate(param *OrderSeparateReq) (*OrderSeparateResp, error) {
	reqParameter := map[string]interface{}{
		"req_data": utils.Struct2Map(param, "", false),
		"version":  Version,
		"req_time": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
	}
	result, err := a.AccessAPISign(SeparateProd, SeparateOrder, http.MethodPost, "", reqParameter)
	if err != nil {
		return nil, err
	}

	bodyResult, err := json.Marshal(result)
	if err != nil {
		return nil, err
	}

	resp := &OrderSeparateResp{}
	if err = json.Unmarshal(bodyResult, resp); err != nil {
		return nil, err
	}
	if resp.Code != SeparateSuccess {
		return nil, fmt.Errorf(resp.Msg)
	}

	return resp, nil
}

// SeparateCancel 订单分账撤销
func (a *API) SeparateCancel(param *SeparateCancelReq) (*SeparateCancelResp, error) {
	reqParameter := map[string]interface{}{
		"req_data": utils.Struct2Map(param, "", false),
		"version":  Version,
		"req_time": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
	}
	result, err := a.AccessAPISign(SeparateProd, SeparateCancel, http.MethodPost, "", reqParameter)
	if err != nil {
		return nil, err
	}

	bodyResult, err := json.Marshal(result)
	if err != nil {
		return nil, err
	}

	resp := &SeparateCancelResp{}
	if err = json.Unmarshal(bodyResult, resp); err != nil {
		return nil, err
	}
	if resp.Code != SeparateSuccess {
		return nil, fmt.Errorf(resp.Msg)
	}

	return resp, err
}

// SeparateFallBack 分账退回
func (a *API) SeparateFallBack(param *SeparateFallReq) (*SeparateFallResp, error) {
	reqParameter := map[string]interface{}{
		"req_data": utils.Struct2Map(param, "", false),
		"version":  Version,
		"req_time": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
	}
	globals.SugarLogger.Debugf("------SeparateFallBack param := %s", utils.Format4Output(param, false))
	result, err := a.AccessAPISign(SeparateProd, SeparateFallBack, http.MethodPost, "", reqParameter)
	globals.SugarLogger.Debugf("------SeparateFallBack result := %s", utils.Format4Output(result, false))
	globals.SugarLogger.Debugf("------SeparateFallBack err := %v", err)
	if err != nil {
		return nil, err
	}

	bodyResult, err := json.Marshal(result)
	if err != nil {
		return nil, err
	}

	resp := &SeparateFallResp{}
	if err = json.Unmarshal(bodyResult, resp); err != nil {
		return nil, err
	}
	if resp.Code != SeparateSuccess {
		return nil, fmt.Errorf(resp.Msg)
	}

	return resp, err
}

// SeparateResultQuery 分账结果查询
func (a *API) SeparateResultQuery(merchantNo, separateNo string) (*SeparateResultQueryResp, error) {
	reqData := map[string]string{
		"merchant_no": merchantNo,
		"separate_no": separateNo,
	}
	reqParameter := map[string]interface{}{
		"req_data": reqData,
		"version":  Version,
		"req_time": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
	}
	result, err := a.AccessAPISign(SeparateProd, SeparateQuery, http.MethodPost, "", reqParameter)
	if err != nil {
		return nil, err
	}

	if result["code"].(string) != SeparateSuccess {
		return nil, fmt.Errorf(result["msg"].(string))
	}
	bodyResult, err := json.Marshal(result["resp_data"])
	if err != nil {
		return nil, err
	}

	resp := &SeparateResultQueryResp{}
	if err = json.Unmarshal(bodyResult, resp); err != nil {
		return nil, err
	}

	return resp, err
}

// SeparateQueryAmt 可分账金额查询
func (a *API) SeparateQueryAmt(merchantNo, logNo, logDate string) (*SeparateQueryAmtResp, error) {
	reqData := map[string]string{
		"merchant_no": merchantNo,
		"log_no":      logNo,
		"log_date":    logDate,
	}
	reqParameter := map[string]interface{}{
		"req_data": reqData,
		"version":  Version,
		"req_time": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
	}
	result, err := a.AccessAPISign(SeparateProd, SeparateQueryAmt, http.MethodPost, "", reqParameter)
	if err != nil {
		return nil, err
	}

	if result["code"].(string) != SeparateSuccess {
		return nil, fmt.Errorf(result["msg"].(string))
	}
	bodyResult, err := json.Marshal(result["resp_data"])
	if err != nil {
		return nil, err
	}

	resp := &SeparateQueryAmtResp{}
	if err = json.Unmarshal(bodyResult, resp); err != nil {
		return nil, err
	}

	return resp, err
}

// QueryCarBin 卡BIN查询
func (a *API) QueryCarBin(orderNo, orgCode, cardNo string) (*BinInfo, error) {
	reqData := map[string]string{
		"version": "1.0",
		"orderNo": orderNo,
		"orgCode": orgCode,
		"cardNo":  cardNo,
	}
	reqParameter := map[string]interface{}{
		"reqData":   reqData,
		"ver":       Version,
		"timestamp": utils.Int64ToStr(time.Now().Unix()),
		"reqId":     utils.GetUUID(),
	}
	result, err := a.AccessAPISign(SeparateAccountProdUrl, SeparateCardBinAction, http.MethodPost, "", reqParameter)
	if err != nil {
		return nil, err
	}

	if result["retCode"].(string) != Success {
		return nil, fmt.Errorf(result["retMsg"].(string))
	}
	bodyResult, err := json.Marshal(result["respData"])
	if err != nil {
		return nil, err
	}

	resp := &BinInfo{}
	if err = json.Unmarshal(bodyResult, resp); err != nil {
		return nil, err
	}

	return resp, err
}

// SaveAuthentication 微信支付宝认证
func (a *API) SaveAuthentication(param *AuthenticationInfo, authType string) error {
	reqData := utils.Struct2Map(param, "", false)
	activityUrl := WeChatAuthentication
	if authType == AuthenticationType {
		reqData["realNameType"] = AuthenticationType
		activityUrl = AlibabaAuthentication
	}
	reqParameter := map[string]interface{}{
		"reqData":   reqData,
		"ver":       Version,
		"timestamp": utils.Int64ToStr(time.Now().Unix()),
		"reqId":     utils.GetUUID(),
	}
	result, err := a.AccessAPISign(SeparateAccountProdUrl, activityUrl, http.MethodPost, "", reqParameter)
	if err != nil {
		return err
	}

	if result["retCode"].(string) != Success {
		return errors.New(result["retMsg"].(string))
	}

	return nil
}

// UpdateAuthentication 实名认证修改
// https://o.lakala.com/#/home/document/detail?id=183
func (a *API) UpdateAuthentication(param *UpdateAuthentication, authType string) error {
	reqData := utils.Struct2Map(param, "", false)
	activityUrl := WeChatUpdateAuthentication
	if authType == AuthenticationType {
		activityUrl = AlibabaUpdateAuthentication
	}
	reqParameter := map[string]interface{}{
		"reqData":   reqData,
		"ver":       Version,
		"timestamp": utils.Int64ToStr(time.Now().Unix()),
		"reqId":     utils.GetUUID(),
	}
	result, err := a.AccessAPISign(SeparateAccountProdUrl, activityUrl, http.MethodPost, "", reqParameter)
	if err != nil {
		return err
	}

	if result["retCode"].(string) != Success {
		return errors.New(result["retMsg"].(string))
	}

	return nil
}

// QueryAuthentication 实名认证查询
// https://o.lakala.com/#/home/document/detail?id=181
func (a *API) QueryAuthentication(param *QueryAuthentication, authType string) (*QueryAuthenticationResp, error) {
	reqData := utils.Struct2Map(param, "", false)
	activityUrl := WeChatQueryAuthentication
	if authType == AuthenticationType {
		reqData["realNameType"] = AuthenticationType
		activityUrl = AlibabaQueryAuthentication
	}
	reqParameter := map[string]interface{}{
		"reqData":   reqData,
		"ver":       Version,
		"timestamp": utils.Int64ToStr(time.Now().Unix()),
		"reqId":     utils.GetUUID(),
	}
	result, err := a.AccessAPISign(SeparateAccountProdUrl, activityUrl, http.MethodPost, "", reqParameter)
	if err != nil {
		return nil, err
	}

	if result["retCode"].(string) != Success {
		return nil, errors.New(result["retMsg"].(string))
	}

	body, err := json.Marshal(result["respData"])
	if err != nil {
		return nil, err
	}

	resp := &QueryAuthenticationResp{}
	if err = json.Unmarshal(body, resp); err != nil {
		return nil, err
	}

	return resp, nil
}

// AccountStatusQuery 开户状态查询
// https://o.lakala.com/#/home/document/detail?id=528
func (a *API) AccountStatusQuery(tradeMode, subMerchantId, merchantNo string) (map[string]interface{}, error) {
	reqParameter := map[string]interface{}{
		"reqData":   map[string]interface{}{"tradeMode": tradeMode, "subMerchantId": subMerchantId, "merchantNo": merchantNo},
		"ver":       Version,
		"timestamp": utils.Int64ToStr(time.Now().Unix()),
		"reqId":     utils.GetUUID(),
	}
	result, err := a.AccessAPISign(PayAccountProdUrl, WeChatAccountStatusQuery, http.MethodPost, "", reqParameter)
	if err != nil {
		return nil, err
	}

	if result["retCode"].(string) != Success {
		return nil, errors.New(result["retMsg"].(string))
	}

	return result["respData"].(map[string]interface{}), nil
}

// SubMerchantInfoQuery 报备查询
// https://o.lakala.com/#/home/document/detail?id=326
func (a *API) SubMerchantInfoQuery(param *SubMerchantInfoQueryReq) ([]*SubMerchantInfoQueryResp, error) {
	reqParameter := map[string]interface{}{
		"reqData": utils.Struct2Map(param, "", false),
	}
	result, err := a.AccessAPISign(SeparateAccountProdUrl, SubMerchantQuery, http.MethodPost, "", reqParameter)
	if err != nil {
		return nil, err
	}

	if result["retCode"].(string) != Success {
		return nil, errors.New(result["retMsg"].(string))
	}

	if result["respData"] != nil && result["respData"].(map[string]interface{}) != nil {
		list := make([]*SubMerchantInfoQueryResp, 0, 0)
		data, err := json.Marshal(result["respData"].(map[string]interface{})["list"])
		if err != nil {
			return nil, err
		}
		if err = json.Unmarshal(data, &list); err != nil {
			return nil, err
		}

		return list, nil
	}

	return nil, errors.New("返回值为空")
}

// SubMerchantInfoQueryReq 报备查询
type SubMerchantInfoQueryReq struct {
	Version         string `json:"version"`         // 必传	String	8	接口版本号	1.0
	OrderNo         string `json:"orderNo"`         // 必传	String	32	订单编号,保证唯一（便于后续跟踪排查问题及核对报文）	14位年月日时（24小时制）分秒+8位的随机数（不重复）如：2021020112000012345678
	OrgCode         string `json:"orgCode"`         // 必传	String	32	机构代码 （合作方在拉卡拉的标识，请联系业务员）	1
	MerInnerNo      string `json:"merInnerNo"`      // 可传	String	32	拉卡拉内部商户号和银联商户号必须传一个，都送以内部商户号为准。	5002022050550024285
	MerCupNo        string `json:"merCupNo"`        // 可传	String	32	拉卡拉内部商户号和银联商户号必须传一个，都送以内部商户号为准。	8222900581207ET
	RegisterChannel string `json:"registerChannel"` // 可选	String	8	报备渠道	UNIONPAY
	RegisterType    string `json:"registerType"`    // 可选	String	64	报备类型	WXZF
	RegisterStatus  string `json:"registerStatus"`  // 可选	String	64	报备状态 SUCCESS：成功；FAIL：失败	SUCCESS
	SubMchId        string `json:"subMchId"`        // 可选	String	64	子商户号
}

// SubMerchantInfoQueryResp 报备查询返回值
type SubMerchantInfoQueryResp struct {
	MerInnerNo          string `json:"merInnerNo"`   // 内部商户号
	SubMchId            string `json:"subMchId"`     // 子商户号
	SubMchIdBank        string `json:"subMchIdBank"` // 交易子商户号
	DcWalletId          string `json:"dcWalletId"`   // 数币钱包ID
	RegisterType        string `json:"registerType"` // 报备类型
	RegisterTypeText    string `json:"registerTypeText"`
	RegisterChannel     string `json:"registerChannel"` // 报备渠道
	RegisterChannelText string `json:"registerChannelText"`
	ChannelId           string `json:"channelId"`      // 渠道号
	ReceOrgNo           string `json:"receOrgNo"`      // 从业机构号
	RegisterTm          string `json:"registerTm"`     // 报备时间
	RegisterStatus      string `json:"registerStatus"` // 报备状态
	ResultCode          string `json:"resultCode"`     // 结果返回码
	ResultMessage       string `json:"resultMessage"`  // 结果描述
}
