package lakala

import (
	"encoding/json"
	"errors"
	"fmt"
	"git.rosy.net.cn/baseapi/platformapi/lakala"
	"git.rosy.net.cn/baseapi/utils"
	"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
	"git.rosy.net.cn/jx-callback/business/model"
	"git.rosy.net.cn/jx-callback/business/model/dao"
	"git.rosy.net.cn/jx-callback/business/partner"
	"git.rosy.net.cn/jx-callback/globals"
	"git.rosy.net.cn/jx-callback/globals/api"
	"strings"
	"time"
)

//#region 进件相关API

// LaKaLaApplyContract 拉卡拉申请签约合同
func LaKaLaApplyContract(ctx *jxcontext.Context, apply *lakala.ApplyContractParam, storeID int) (*lakala.ApplyContract, error) {
	apply.OrderNo = lakala.GetOrderNumber(10)
	apply.RetUrl = lakala.ApplyContractCallback
	contractObj, err := api.LaKaLaApi.ApplyElectronicContract(apply)
	if err != nil {
		return nil, err
	}

	if contractObj.RespData != nil {
		db := dao.GetDB()
		incomingObj := &model.LakalaContract{
			StoreId:         storeID,
			ContractId:      contractObj.RespData.OrderNo,
			ContractApplyId: utils.Int64ToStr(contractObj.RespData.EcApplyId),
			ContractStatus:  "WAIT_AUDIT ",
			ApplyType:       apply.EcTypeCode,
			Desc:            "申请中",
		}
		dao.WrapAddIDCULEntity(incomingObj, ctx.GetUserName())
		if err = dao.CreateEntity(db, incomingObj); err != nil {
			return nil, err
		}

	}
	return contractObj, nil
}

// LaKaLaApplyContractByPeople 申请人工审核 ApplyElectronicContractByPeople
func LaKaLaApplyContractByPeople(storeId int, apply *lakala.ApplyContractByPeople) (string, error) {
	if apply.Version == "" {
		apply.Version = "1.0"
	}
	//apply.RetUrl = lakala.ApplyContractByPeopleCallback
	err := api.LaKaLaApi.ApplyElectronicContractByPeople(apply)
	if err != nil {
		return "", fmt.Errorf("申请人工审核失败:%v", err)
	}

	contract, err := dao.GetStoreContract(dao.GetDB(), storeId, "", utils.Int64ToStr(apply.EcApplyId))
	if err != nil {
		return "", err
	}

	contract.ContractStatus = "people"
	contract.Desc = "申请人工审核"
	dao.UpdateEntity(dao.GetDB(), contract, "ContractStatus")
	return "", nil
}

// QueryElectronicContract 人工复合结果查询
func QueryElectronicContract(orderNo string, orgId int, ecApplyId string, storeID int) (*lakala.ElectronicContractStatus, error) {
	db := dao.GetDB()
	merchantInfo, err := dao.GetStoreContract(db, storeID, orderNo, "")
	if err != nil {
		return nil, err
	}

	contractObj, err := api.LaKaLaApi.QueryElectronicContract(orderNo, orgId, ecApplyId)
	if err != nil {
		return nil, err
	}
	merchantInfo.ContractStatus = contractObj.AuditStatus
	merchantInfo.Desc = contractObj.AuditDesc
	dao.UpdateEntity(db, merchantInfo, "ContractStatus")

	return contractObj, nil
}

// QueryElectronic 电子合同查询
func QueryElectronic(orderNo string, orgId int, ecApplyId string, storeID int) (*lakala.QueryElectronicResp, error) {
	db := dao.GetDB()
	merchantInfo, err := dao.GetStoreContract(db, storeID, orderNo, "")
	if err != nil {
		return nil, err
	}

	contractObj, err := api.LaKaLaApi.QueryElectronic(orderNo, orgId, ecApplyId)
	if err != nil {
		return nil, err
	}
	merchantInfo.ContractStatus = contractObj.EcStatus
	dao.UpdateEntity(db, merchantInfo, "ContractStatus")

	return contractObj, nil
}

// LaKaLaInComing 商户进件
func LaKaLaInComing(ctx *jxcontext.Context, incoming *lakala.MerchantIncomingReq, storeId int) (string, error) {
	merchantNo, status, err := api.LaKaLaApi.MerchantIncoming(incoming)
	if err != nil {
		return "", err
	}
	incomingObj := &model.LakalaIncoming{
		StoreId:        storeId,
		MerchantNo:     merchantNo,
		MerchantStatus: status,
	}
	dao.WrapAddIDCULEntity(incomingObj, ctx.GetUserName())

	if err = dao.CreateEntity(dao.GetDB(), incomingObj); err != nil {
		return "", err
	}

	return status, nil
}

// GetMerchantInfo 获取门店商户详情
func GetMerchantInfo(merchantNo string) (*lakala.MerchantObj, error) {
	result, err := api.LaKaLaApi.GetMerchantInfo(merchantNo)
	if err != nil {
		return nil, err
	}
	db := dao.GetDB()
	merchantInfo, err := dao.GetStoreInfoByMerchantID(db, merchantNo, 0, "", "")
	if err != nil {
		return nil, err
	}

	if merchantInfo.TermNo == "" {
		merchantInfo.TermNo = result.Customer.TermNo
	}
	merchantInfo.MerchantStatus = result.Customer.CustomerStatus
	if merchantInfo.MerchantNo2 == "" {
		merchantInfo.MerchantNo2 = result.Customer.ExternalCustomerNo
	}
	dao.UpdateEntity(db, merchantInfo, "TermNo", "MerchantStatus", "MerchantNo2")

	return result, err
}

// GetPosTerimeInfo 获取门店商户详情
func GetPosTerimeInfo(posSn string) (*lakala.TerminalInfo, error) {
	result, err := api.LaKaLaApi.GetTerminalInfo(posSn)
	if err != nil {
		return nil, err
	}
	return result, err
}

// QueryCityCode 获取拉卡拉code列表
func QueryCityCode(parentCode string) ([]*lakala.OrganizationList, error) {
	return api.LaKaLaApi.GetOrganizationCode(parentCode)
}

// QueryBankList 获取地方银行列表
func QueryBankList(areaCode, bankName string) ([]*lakala.BankListResult, error) {
	if areaCode == "" {
		return nil, fmt.Errorf("地区编码不能为空")
	}
	return api.LaKaLaApi.GetBankList(areaCode, bankName)
}

// GetCustomerCategory 获取门店类别
func GetCustomerCategory(businessScene, parentCode string) ([]*lakala.BusinessResult, error) {
	return api.LaKaLaApi.GetMerchantMcc(businessScene, parentCode)
}

// MerchantFeeQuery 商户费率查询
func MerchantFeeQuery(customerNo, productCode string) (*lakala.MerchantFeeResp, error) {
	return api.LaKaLaApi.MerchantFeeQuery(customerNo, productCode)
}

// MerchantFeeChange 商户费率信息变更
func MerchantFeeChange(param *lakala.FeeChangeReq, customerNo string) (int64, string, error) {
	changeId, status, err := api.LaKaLaApi.MerchantFeeChange(param, customerNo)
	if err != nil {
		return 0, "", err
	}

	if changeId != model.NO {
		db := dao.GetDB()
		merchant, err := dao.GetStoreInfoByMerchantID(db, customerNo, 0, "", "")
		if err != nil {
			return 0, "", err
		}
		merchant.FeeId = utils.Int64ToStr(changeId)
		merchant.FeeStatus = status
		dao.UpdateEntity(db, merchant, "FeeId", "FeeStatus")
	}

	return changeId, status, err
}

// UpdateSettleInfo 查询/修改结算信息
func UpdateSettleInfo(customerNo string, param *lakala.UpdateSettleInfoReq) (*lakala.UpdateSettleInfoReq, string, error) {
	updateResult, queryResult, err := api.LaKaLaApi.UpdateSettleInfo(customerNo, param)
	if err != nil {
		return nil, "", err
	}

	db := dao.GetDB()
	merchant, err := dao.GetStoreInfoByMerchantID(db, customerNo, 0, "", "")
	if err != nil {
		return nil, "", err
	}
	if param == nil {
		return queryResult, "", err
	}

	merchant.SettleId = utils.Int64ToStr(updateResult.ReviewRelatedId)
	merchant.SettleStatus = updateResult.Message
	dao.UpdateEntity(db, merchant, "SettleID", "SettleStatus")
	return nil, updateResult.Message, nil
}

// MerchantUpdateBaseInfo 基本信息变更
func MerchantUpdateBaseInfo(customerNo string, param *lakala.UpdateBaseInfoReq) (string, error) {
	basic, err := api.LaKaLaApi.UpdateBaseInfo(customerNo, param)
	if err != nil {
		return "", err
	}

	if basic.ReviewRelatedId != model.NO {
		db := dao.GetDB()
		merchant, err := dao.GetStoreInfoByMerchantID(db, customerNo, 0, "", "")
		if err != nil {
			return "", err
		}
		merchant.BasicId = utils.Int64ToStr(basic.ReviewRelatedId)
		merchant.BasicStatus = basic.Message
		dao.UpdateEntity(db, merchant, "BasicId", "BasicStatus")
		return merchant.BasicId, nil
	}

	return "", fmt.Errorf("UpdateBaseInfo 修改异常,联系管理员")
}

// QueryExamine 查询门店变更审核状态
func QueryExamine(merchantId, reviewRelatedId string) (map[string]string, error) {
	reviewPass, reviewResult, err := api.LaKaLaApi.QueryMerchantReviewStatus(reviewRelatedId)
	if err != nil {
		return nil, err
	}
	db := dao.GetDB()
	merchant, err := dao.GetStoreInfoByMerchantID(db, merchantId, 0, "", "")
	if err != nil {
		return nil, err
	}

	updateField := make([]string, 0, 0)
	switch reviewRelatedId {
	case merchant.FeeId:
		merchant.FeeStatus = reviewPass
		updateField = append(updateField, "FeeStatus")
	case merchant.SettleId:
		merchant.SettleStatus = reviewPass
		updateField = append(updateField, "SettleStatus")
	case merchant.BasicId:
		merchant.BasicStatus = reviewPass
		updateField = append(updateField, "BasicStatus")
	case merchant.LicenseId:
		merchant.LicenseStatus = reviewPass
		updateField = append(updateField, "LicenseStatus")
	}
	if len(updateField) != 0 {
		dao.UpdateEntity(db, merchant, updateField...)
	}

	return map[string]string{"status": reviewPass, "desc": reviewResult}, err
}

// CheckIsUploadPhoto 查看门店是否需要补充照片
func CheckIsUploadPhoto(customerNo string) (*lakala.OpenCustomerExtImgVo, error) {
	return api.LaKaLaApi.CheckImgIsSupplement(customerNo)
}

// ImgSupplement 补充照片
func ImgSupplement(param *lakala.ImgSupplementReq) error {
	if param.ExtCustomerNo == "" {
		return fmt.Errorf("商户号不能为空")
	}
	return api.LaKaLaApi.ImgSupplement(param)
}

// GetMerchantReportStatus 查看银联报备状态
func GetMerchantReportStatus(orgCode, agentNo, customerNo string) (*lakala.OpenUnionpayMerchantVo, error) {
	return api.LaKaLaApi.GetMerchantReportStatus(orgCode, agentNo, customerNo)
}

// GetMerchantTerminal 获取终端报备信息
func GetMerchantTerminal(orgCode, agentNo, externalCustomerNo, posSn string) (*lakala.OpenUnionpayTermVo, error) {
	return api.LaKaLaApi.GetMerchantTerminal(orgCode, agentNo, externalCustomerNo, posSn)
}

// SupplementBusinessLicense 变更营业执照
func SupplementBusinessLicense(param *lakala.BusinessLicenseReq) (string, error) {
	licenseId, status, err := api.LaKaLaApi.SupplementBusinessLicense(param)
	if err != nil {
		return "", err
	}

	db := dao.GetDB()
	merchant, err := dao.GetStoreInfoByMerchantID(db, param.ExternalCustomerNo, 0, "", "")
	if err != nil {
		return "", err
	}
	merchant.LicenseId = licenseId
	merchant.LicenseStatus = status
	if _, err = dao.UpdateEntity(db, merchant, "LicenseId", "LicenseStatus"); err != nil {
		return "", err
	}

	return status, nil
}

// UnionPayMerInfo 联防机制查询(失信人名单)
func UnionPayMerInfo(larName, larIdCard string) (*lakala.DishonestPerson, error) {
	return api.LaKaLaApi.UnionPayMerInfo(larName, larIdCard)
}

//#endregion

//#region 分账相关

// CreateSeparate 创建分账门店
func CreateSeparate(req *lakala.CreateSeparateReq) (string, error) {
	req.OrderNo = lakala.GetOrderNumber(8)
	req.RetUrl = lakala.CallbackLaKaLaShopUrl
	applyID, err := api.LaKaLaApi.CreateSeparate(req)
	if err != nil {
		return "", err
	}

	db := dao.GetDB()
	merchant, err := dao.GetStoreInfoByMerchantID(db, req.MerInnerNo, 0, "", "")
	if err != nil {
		return "", err
	}

	merchant.OrderID = req.OrderNo
	merchant.ApplyID = applyID
	merchant.ThingType = model.ThingTypeSeparate
	merchant.Operate = model.OperateTypeCreate
	merchant.OperateStatus = model.OperateStatusReview
	merchant.Remark = fmt.Sprintf("创建分账:%s", req.OrderNo)
	if _, err = dao.UpdateEntity(db, merchant, "OrderID", "ApplyID", "ThingType", "Operate", "OperateStatus", "Remark"); err != nil {
		return "", err
	}

	return applyID, nil
}

// SeparateModify 变更分账门店
func SeparateModify(param *lakala.SeparateModifyReq) (string, error) {
	db := dao.GetDB()
	merchant, err := dao.GetStoreInfoByMerchantID(db, param.MerInnerNo, 0, "", "")
	if err != nil {
		return "", err
	}

	if merchant.OperateStatus == model.OperateStatusReview {
		return "", fmt.Errorf("有待审核项目,请审核完成后再变更")
	}

	param.OrderNo = lakala.GetOrderNumber(8)
	param.RetUrl = lakala.CallbackLaKaLaShopUrl
	applyID, err := api.LaKaLaApi.SeparateModify(param)
	if err != nil {
		return "", err
	}

	merchant.OrderID = param.OrderNo
	merchant.ApplyID = applyID
	merchant.ThingType = model.ThingTypeSeparate
	merchant.Operate = model.OperateTypeUpdate
	merchant.OperateStatus = model.OperateStatusReview
	merchant.Remark = fmt.Sprintf("修改分账:%s", param.OrderNo)
	if _, err = dao.UpdateEntity(db, merchant, "OrderID", "ApplyID", "ThingType", "Operate", "OperateStatus"); err != nil {
		return "", err
	}

	return applyID, nil
}

// SeparateQuery 分账信息查询
func SeparateQuery(merInnerNo, orgCode string) (*lakala.SeparateQueryResp, error) {
	param := &lakala.SeparateQueryReq{
		Version:  lakala.Version2,
		OrderNo:  lakala.GetOrderNumber(8),
		OrgCode:  orgCode,
		MerCupNo: merInnerNo,
	}
	return api.LaKaLaApi.SeparateQuery(param)
}

// CreateSeparateRecipient 创建分账接收方
func CreateSeparateRecipient(ctx *jxcontext.Context, param *lakala.CreateSeparateRecipientReq) (string, error) {
	param.OrderNo = lakala.GetOrderNumber(8)
	receiverNo, err := api.LaKaLaApi.CreateSeparateRecipient(param)
	if err != nil {
		return "", err
	}

	receiver := &model.LakalaRecipient{}
	dao.WrapAddIDCULEntity(receiver, ctx.GetUserName())
	receiver.ReceiverNo = receiverNo
	receiver.ReceiverName = param.ReceiverName
	receiver.OrgCode = param.OrgCode
	receiver.Status = model.ReceiverStatusValid
	receiver.Remark = fmt.Sprintf("创建分账接收方:%s", param.OrderNo)

	if err = dao.CreateEntity(dao.GetDB(), receiver); err != nil {
		return "", err
	}
	return receiverNo, err
}

// UpdateSeparateRecipient 修改分账接收方
func UpdateSeparateRecipient(param *lakala.UpdateSeparateRecipientReq) (string, error) {
	param.OrderNo = lakala.GetOrderNumber(8)
	orderNo, err := api.LaKaLaApi.UpdateSeparateRecipient(param)
	if err != nil {
		return "", err
	}

	db := dao.GetDB()
	recipient, err := dao.GetRecipientByMerchantID(db, param.ReceiverNo)
	recipient.ReceiverName = param.ReceiverName
	recipient.Status = param.Status
	recipient.Remark = fmt.Sprintf("修改分账接收方:%s", param.OrderNo)

	_, err = dao.UpdateEntity(db, recipient, "ReceiverName", "Status", "Remark")
	if err != nil {
		return "", err
	}
	return orderNo, nil
}

// QuerySeparateRecipient 分账方详细信息查询
func QuerySeparateRecipient(orderNo, receiverNo string) (*lakala.QuerySeparateRecipientResp, error) {
	return api.LaKaLaApi.QuerySeparateRecipient(orderNo, receiverNo)
}

// ApplyBind 申请绑定分账关系
func ApplyBind(param *lakala.SeparateApplyBindReq) (*lakala.SeparateApplyBindResp, error) {
	param.OrderNo = lakala.GetOrderNumber(8)
	param.RetUrl = lakala.CallbackLaKaLaSeparateBindUrl
	applyInfo, err := api.LaKaLaApi.ApplyBind(param)
	if err != nil {
		return nil, err
	}

	db := dao.GetDB()
	merchant, err := dao.GetStoreInfoByMerchantID(db, param.MerInnerNo, 0, "", "")
	if err != nil {
		return applyInfo, err
	}
	bind := map[string]*model.BindAccountObj{param.ReceiverNo: &model.BindAccountObj{
		ApplyId: utils.Int64ToStr(applyInfo.RespData.ApplyId),
		Status:  "0",
		Remark:  "新增绑定",
	}}
	bodyBind, _ := json.Marshal(bind)
	merchant.BindAccount = string(bodyBind)
	_, err = dao.UpdateEntity(db, merchant, "BindAccount")
	if err != nil {
		return applyInfo, err
	}
	return applyInfo, nil
}

// SeparateUnBind 申请解除绑定
func SeparateUnBind(param *lakala.SeparateUnBindReq) error {
	param.OrderNo = lakala.GetOrderNumber(8)
	param.RetUrl = lakala.CallbackLaKaLaSeparateBindUrl
	applyId, err := api.LaKaLaApi.SeparateUnBind(param)
	if err != nil {
		return err
	}
	db := dao.GetDB()
	merchant, err := dao.GetStoreInfoByMerchantID(db, param.MerInnerNo, 0, "", "")
	if err != nil {
		return err
	}

	unBind := make(map[string]*model.BindAccountObj, 0)
	if err = json.Unmarshal([]byte(merchant.BindAccount), &unBind); err != nil {
		return err
	}

	unBind[param.ReceiverNo] = &model.BindAccountObj{
		ApplyId: applyId,
		Status:  "0",
		Remark:  "解除绑定",
	}

	bodyBind, _ := json.Marshal(unBind)
	merchant.BindAccount = string(bodyBind)
	if _, err = dao.UpdateEntity(db, merchant, "BindAccount"); err != nil {
		return err
	}

	return nil
}

// SeparateQueryAmt 可分账金额查询
func SeparateQueryAmt(ctx *jxcontext.Context, merchantNo, logDate, logNo, vendorOrderId string) (*lakala.SeparateQueryAmtResp, error) {
	result, err := api.LaKaLaApi.SeparateQueryAmt(merchantNo, logNo, logDate)
	if err != nil {
		return nil, err
	}

	separate, err := dao.GetSeparateAmtByOrderID(vendorOrderId, "", logNo)
	if separate != nil {
		separate.TotalAmt = result.TotalSeparateAmt
		separate.CanAmt = result.CanSeparateAmt
		dao.UpdateEntity(dao.GetDB(), separate, "TotalAmt", "ActualSeparateAmt")
	} else {
		order, _ := partner.CurOrderManager.LoadOrder(vendorOrderId, model.VendorIDJX)
		separate = &model.LakalaSeparateAmt{
			MerchantNo:    merchantNo,
			VendorOrderID: vendorOrderId,
			StoreId:       order.JxStoreID,
			CmdType:       lakala.SeparateType_SEPATRATE,
			Status:        "1",
			LogNo:         logNo,
			LogDate:       time.Now(),
			SeparateNo:    "",
			OutSeparateNo: "",
			CalType:       "",
			FinishDate:    "",
			TotalAmt:      result.TotalSeparateAmt,
			CanAmt:        result.CanSeparateAmt,
			TotalFeeAmt:   "",
			FinalStatus:   "",
			DetailData:    "",
			Remark:        "",
		}
		dao.WrapAddIDCULEntity(separate, ctx.GetUserName())
		err = dao.CreateEntity(dao.GetDB(), separate)
	}

	return result, err
}

// Separate 分账
func Separate(ctx *jxcontext.Context, param *lakala.OrderSeparateReq, vendorOrderId string) (*lakala.OrderSeparateResp, error) {
	separateObj, err := dao.GetSeparateAmtByOrderID(vendorOrderId, "", param.LogNo)
	if err != nil {
		return nil, err
	}

	param.NotifyUrl = lakala.CallbackLaKaLaSeparateUrl
	globals.SugarLogger.Debugf("------Separate param--:%s", utils.Format4Output(param, false))
	resp, err := api.LaKaLaApi.Separate(param)
	if err != nil {
		return nil, err
	}

	globals.SugarLogger.Debugf("------Separate resp--:%s", utils.Format4Output(resp, false))
	recv, _ := json.Marshal(param.RecvDatas)
	separateObj.OutSeparateNo = param.OutSeparateNo
	separateObj.SeparateNo = resp.RespData.SeparateNo
	separateObj.CalType = param.CalType
	separateObj.Status = resp.RespData.Status
	separateObj.Remark += `->分账`
	separateObj.DetailData = string(recv)
	separateObj.CmdType = lakala.SeparateType_SEPATRATE
	t, err := time.Parse("20060102", param.LogDate)
	if err != nil {
		t = time.Now()
	}
	separateObj.LogDate = t
	globals.SugarLogger.Debugf("------Separate separateObj--:%s", utils.Format4Output(separateObj, false))
	_, err = dao.UpdateEntity(dao.GetDB(), separateObj)
	globals.SugarLogger.Debugf("------Separate err--:%v", err)

	return resp, err
}

// SeparateResultQuery 分账结果查询
func SeparateResultQuery(merchantNo, separateNo string) (*lakala.SeparateResultQueryResp, error) {
	result, err := api.LaKaLaApi.SeparateResultQuery(merchantNo, separateNo)
	if err != nil {
		return nil, err
	}

	db := dao.GetDB()
	recordsObj, err := dao.GetSeparateRecords(db, merchantNo, separateNo, result.CmdType)
	if err != nil {
		return nil, err
	}
	recordsObj.UpdatedAt = time.Now()
	recordsObj.ActualSeparateAmt = result.ActualSeparateAmt
	recordsObj.TotalFeeAmt = result.TotalFeeAmt
	recordsObj.Status = result.Status
	recordsObj.SeparateNo = result.SeparateNo
	recordsObj.OutSeparateNo = result.OutSeparateNo
	recordsObj.TotalAmt = result.TotalAmt
	recv := make([]*lakala.RecvDatasParam, 0, 0)
	for _, v := range result.DetailDatas {
		recv = append(recv, &lakala.RecvDatasParam{
			RecvNo:        v.RecvNo,
			SeparateValue: utils.Int64ToStr(v.Amt),
		})
	}
	recvObj, _ := json.Marshal(recv)
	recordsObj.DetailData = string(recvObj)
	if _, err = dao.UpdateEntity(db, recordsObj, "DetailData", "Status", "TotalFeeAmt", "UpdatedAt", "TotalAmt", "ActualSeparateAmt", "DetailData"); err != nil {
		return nil, err
	}

	return result, nil
}

// SeparateCancel 订单分账撤销
func SeparateCancel(merchantNo, separateNo string) (*lakala.SeparateCancelResp, error) {
	db := dao.GetDB()
	separateAmt, err := dao.GetSeparateRecords(db, merchantNo, separateNo, "")
	if err != nil {
		return nil, err
	}
	result, err := api.LaKaLaApi.SeparateCancel(&lakala.SeparateCancelReq{
		MerchantNo:          merchantNo,
		OriginSeparateNo:    separateNo,
		OriginOutSeparateNo: "",
		OutSeparateNo:       lakala.GetOrderNumber(8),
		TotalAmt:            separateAmt.TotalAmt,
	})
	if err != nil {
		return nil, err
	}

	separateAmt.CmdType = lakala.SeparateType_CANCEL
	separateAmt.Status = result.RespData.Status
	//separateAmt.SeparateNo = result.RespData.SeparateNo
	separateAmt.Remark += "->分账撤销"

	if _, err = dao.UpdateEntity(db, separateAmt, "CmdType", "Status", "Remark"); err != nil {
		return nil, err
	}

	return result, err
}

// SeparateFallBack 分账退回
func SeparateFallBack(merchantNo, separateNo, reason string) (*lakala.SeparateFallResp, error) {
	db := dao.GetDB()
	separateAmt, err := dao.GetSeparateRecords(db, merchantNo, separateNo, "")
	if err != nil {
		return nil, err
	}

	recv := make([]*lakala.RecvDatasParam, 0, 0)
	if err = json.Unmarshal([]byte(separateAmt.DetailData), &recv); err != nil {
		return nil, err
	}
	if len(recv) == 0 {
		return nil, fmt.Errorf("数据异常[%s],未获取到分账详细", separateNo)
	}

	isBack := false
	for _, v := range recv {
		if strings.Contains(v.RecvNo, "SR") {
			isBack = true
		}
	}
	//先了解分账回退这个功能是怎么用的，多次跟咱们同步。分账回退这个接口，用的场景是订单发生退款时，
	//把已经分给接收方（SR开头）的资金回退给商户，用作资金平账的。因为退款是从商户收款账户资金里退的
	//822开头的就是商家自己不需要回退
	if !isBack {
		return nil, nil
	}

	param := &lakala.SeparateFallReq{
		MerchantNo:       merchantNo,
		OriginSeparateNo: separateNo,
		OutSeparateNo:    lakala.GetOrderNumber(8),
		FallbackReason:   reason,
		TotalAmt:         separateAmt.TotalAmt,
		OriginRecvDatas:  nil,
	}
	originRecvDatas := make([]*lakala.OriginRecvDatas, 0, len(recv))
	for _, v := range recv {
		originRecvDatas = append(originRecvDatas, &lakala.OriginRecvDatas{
			RecvNo: v.RecvNo,
			Amt:    v.SeparateValue,
		})
	}
	param.OriginRecvDatas = originRecvDatas

	result, err := api.LaKaLaApi.SeparateFallBack(param)
	if err != nil {
		return nil, err
	}

	separateAmt.CmdType = lakala.Separate_FALLBACK
	separateAmt.Status = result.RespData.Status
	separateAmt.Remark += "->分账退回"
	dao.UpdateEntity(db, separateAmt, "CmdType", "Status", "Remark")

	return result, nil
}

func GetCardBin(orgCode, cardNo string) (*lakala.BinInfo, error) {
	result, err := api.LaKaLaApi.QueryCarBin(lakala.GetOrderNumber(8), orgCode, cardNo)
	return result, err
}

// SaveAuthentication 支付宝/微信认证
func SaveAuthentication(param *lakala.AuthenticationInfo, authType string) error {
	return api.LaKaLaApi.SaveAuthentication(param, authType)
}

// UpdateAuthentication 修改认证
func UpdateAuthentication(param *lakala.UpdateAuthentication, authType string) error {
	return api.LaKaLaApi.UpdateAuthentication(param, authType)
}

// QueryAuthentication 认证查询
func QueryAuthentication(param *lakala.QueryAuthentication, authType string) (*lakala.QueryAuthenticationResp, error) {
	return api.LaKaLaApi.QueryAuthentication(param, authType)
}

// AccountStatusQuery 开户状态查询
func AccountStatusQuery(tradeMode, subMerchantId, merchantNo string) (map[string]interface{}, error) {
	return api.LaKaLaApi.AccountStatusQuery(tradeMode, subMerchantId, merchantNo)
}

// SubMerchantInfoQuery 报备查询
func SubMerchantInfoQuery(merInnerNo, merCupNo string) ([]*lakala.SubMerchantInfoQueryResp, error) {
	if merInnerNo == "" && merCupNo == "" {
		return nil, errors.New("内部商户号和银联号必须填写一个")
	}
	param := &lakala.SubMerchantInfoQueryReq{
		Version:    "1.0",
		OrderNo:    lakala.GetOrderNumber(8),
		OrgCode:    lakala.OrgCode,
		MerInnerNo: "",
		MerCupNo:   "",
	}
	if merInnerNo != "" {
		param.MerInnerNo = merInnerNo
	} else {
		param.MerCupNo = merCupNo
	}
	return api.LaKaLaApi.SubMerchantInfoQuery(param)
}

//#endregion

//#region 订单相关

// CreateOrder 创建拉卡拉交易订单
func CreateOrder(ctx *jxcontext.Context, vendorOrderID, merchantNo, callbackUrl string, vendorId int) (*lakala.CreateOrderResp, error) {
	order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, vendorId)
	if err != nil {
		return nil, err
	}
	param := &lakala.CreateOrderReq{
		OutOrderNo:         order.VendorOrderID,
		MerchantNo:         merchantNo,
		TotalAmount:        order.ActualPayPrice,
		OrderEfficientTime: time.Now().Add(1 * time.Hour).Format("20060102150405"),
		OrderInfo:          fmt.Sprintf("门店扫码订单:%d", order.OrderSeq),
		NotifyUrl:          lakala.OrderStatusCallback,
		SupportRepeatPay:   1,
		CallbackUrl:        callbackUrl,
		SupportRefund:      1,
	}

	result, err := api.LaKaLaApi.CreateOrder(param)
	if err != nil {
		return nil, err
	}

	orderPay := &model.OrderPay{
		PayOrderID:    result.PayOrderNo,
		PayType:       model.PayTypeLaKaLa,
		VendorPayType: lakala.PayWayAPP,
		TransactionID: "",
		VendorOrderID: order.VendorOrderID,
		VendorID:      order.VendorID,
		Status:        0,
		PayCreatedAt:  time.Now(),
		PrepayID:      result.PayOrderNo,
		CodeURL:       "",
		TotalFee:      int(order.ActualPayPrice),
	}
	dao.WrapAddIDCULDEntity(orderPay, ctx.GetUserName())
	err = dao.CreateEntity(dao.GetDB(), orderPay)

	separate := &model.LakalaSeparateAmt{
		MerchantNo:        merchantNo,
		VendorOrderID:     order.VendorOrderID,
		StoreId:           order.JxStoreID,
		CmdType:           lakala.SeparateType_SEPATRATE,
		Status:            "1",
		LogNo:             "",
		LogDate:           time.Now(),
		SeparateNo:        "",
		OutSeparateNo:     "",
		CalType:           "",
		FinishDate:        "",
		TotalAmt:          "",
		ActualSeparateAmt: "",
		TotalFeeAmt:       "",
		FinalStatus:       "",
		DetailData:        "",
		Remark:            "",
	}
	dao.WrapAddIDCULEntity(separate, ctx.GetUserName())
	err = dao.CreateEntity(dao.GetDB(), separate)

	return result, nil
}

// CloseOrder 关闭待支付订单
func CloseOrder(merchantId, vendorOrderId string, vendorId int) (string, error) {
	param := &lakala.CloseOrderReq{
		MerchantNo: merchantId,
		OutOrderNo: vendorOrderId,
		PayOrderNo: "",
		ChannelId:  "",
	}
	result, err := api.LaKaLaApi.CloseOrder(param)
	if err != nil {
		return "", err
	}
	order, err := partner.CurOrderManager.LoadOrder(vendorOrderId, vendorId)
	if err != nil {
		return "", err
	}

	switch result {
	case lakala.OrderCloseStatusPayFail, lakala.OrderCloseStatusExpire, lakala.OrderCloseStatusCancel, lakala.OrderCloseStatusRefund, lakala.OrderCloseStatusClose:
		order.Status = model.OrderStatusCanceled
		order.VendorStatus = result
		dao.UpdateEntity(dao.GetDB(), order, "Status", "VendorStatus")
	}

	return result, err
}

// QueryOrder 收银台订单查询
func QueryOrder(vendorOrderId, merchantId string, vendorId int) (*lakala.QueryOrderResp, error) {
	result, err := api.LaKaLaApi.QueryOrder(vendorOrderId, merchantId)
	if err != nil {
		return nil, err
	}

	order, err := partner.CurOrderManager.LoadOrder(vendorOrderId, vendorId)
	if err != nil {
		return nil, err
	}
	switch result.OrderStatus {
	case lakala.OrderCloseStatusPayFail, lakala.OrderCloseStatusExpire, lakala.OrderCloseStatusCancel, lakala.OrderCloseStatusRefund, lakala.OrderCloseStatusClose:
		order.Status = model.OrderStatusCanceled
		order.VendorStatus = result.OrderStatus
	case lakala.OrderCloseStatusPaySuccess:
		order.Status = model.OrderStatusFinished
		order.VendorStatus = result.OrderStatus
		order.OrderFinishedAt = time.Now()
	}
	dao.UpdateEntity(dao.GetDB(), order, "Status", "VendorStatus", "OrderFinishedAt")

	return result, nil
}

// CloseOrderByMini 聚合支付关单,关单重新拉起支付
func CloseOrderByMini(merchantNo, termNo, orderNo, ip string) error {
	param := &lakala.ClosePayMiniOrder{
		MerchantNo:       merchantNo,
		TermNo:           termNo,
		OriginOutTradeNo: orderNo,
		OriginTradeNo:    "",
		LocationInfo: struct {
			RequestIp   string `json:"request_ip"`
			BaseStation string `json:"base_station"`
			Location    string `json:"location"`
		}{
			RequestIp: ip,
		},
	}
	return api.LaKaLaApi.ClosePay(param)
}

//#endregion

//#region 账户相关

// QueryBillBalance 查询账户余额
func QueryBillBalance(orgNo, merchantNo, payType string) (*lakala.QueryBillBalanceResp, error) {
	result, err := api.LaKaLaApi.QueryBillBalance(&lakala.QueryBillBalanceReq{
		OrgNo:      orgNo,
		MerchantNo: merchantNo,
		PayType:    payType,
	})

	return result, err
}

// EwalletWithdrawD1 申请提现
func EwalletWithdrawD1(ctx *jxcontext.Context, orgNo, merchantNo, payType, drawAmt string) error {
	param := &lakala.EwalletWithdrawD1Req{
		OrgNo:      orgNo,
		MerchantNo: merchantNo,
		DrawAmt:    drawAmt,
		NotifyUrl:  lakala.BillProdCallbackUrl,
		MerOrderNo: lakala.GetOrderNumber(8),
		PayNo:      "",
		PayType:    payType,
		Remark:     "",
		Summary:    "",
		BankId:     "",
	}
	drawJnl, _, err := api.LaKaLaApi.EwalletWithdrawD1(param)
	if err != nil {
		return err
	}
	withdrawal := &model.LakalaWithdrawal{
		CreatedTime:     time.Now(),
		MercId:          merchantNo,
		DrawJnl:         drawJnl,
		ReqDate:         "",
		DrawAmt:         drawAmt,
		DrawFee:         "",
		BatchAutoSettle: "01",
		DrawState:       "DRAW.ACCEPTED",
		DrawMode:        "",
		Memo:            "",
		CompleteTime:    time.Now(),
	}
	dao.WrapAddIDCULEntity(withdrawal, ctx.GetUserName())
	if err = dao.CreateEntity(dao.GetDB(), withdrawal); err != nil {
		return err
	}

	return nil
}

// EwalletWithdrawQuery 提现结果查询
func EwalletWithdrawQuery(ctx *jxcontext.Context, orgNo, merchantNo, drawJnl string) (*lakala.EwalletWithdrawQueryResp, error) {
	resp, err := api.LaKaLaApi.EwalletWithdrawQuery(&lakala.EwalletWithdrawQueryReq{
		OrgNo:      orgNo,
		MerchantNo: merchantNo,
		DrawJnl:    drawJnl,
	})
	if err != nil {
		return nil, err
	}

	db := dao.GetDB()
	withDraw, err := dao.GetEwalletWithDraw(db, merchantNo, drawJnl)
	if err != nil {
		return nil, err
	}

	withDraw.UpdatedAt = time.Now()
	withDraw.LastOperator = ctx.GetUserName()
	withDraw.CreatedTime = utils.Str2Time(resp.CreatedTime)
	withDraw.CompleteTime = utils.Str2Time(resp.CompleteTime)
	withDraw.ReqDate = resp.ReqDate
	withDraw.DrawFee = resp.DrawFee
	withDraw.DrawAmt = resp.DrawAmt
	withDraw.BatchAutoSettle = resp.BatchAutoSettle
	withDraw.DrawState = resp.DrawState
	withDraw.DrawMode = resp.DrawMode
	withDraw.Memo = resp.Memo

	if _, err = dao.UpdateEntity(db, withDraw); err != nil {
		return nil, err
	}
	return resp, nil
}

// SettleDrawPattern 提款模式设置
func SettleDrawPattern(param *lakala.SettleDrawPatternReq) error {
	param.NotifyUrl = lakala.BillProdCallbackUrl
	return api.LaKaLaApi.SettleDrawPattern(param)
}

// EwalletSettleQuery 提款模式查询
func EwalletSettleQuery(orgCode, merchantId string) (*lakala.EwalletSettleQueryResp, error) {
	return api.LaKaLaApi.EwalletSettleQuery(orgCode, merchantId)
}

//#endregion

//#region 图片上传

func UploadImg(filePath, imgType, sourcechnl, isOcr string) (*lakala.UploadImgResp, error) {
	return api.LaKaLaApi.FileUpload(filePath, imgType, sourcechnl, isOcr)
}

// UploadAttachmentImg 分账附件上传
func UploadAttachmentImg(orgCode, attType, attExtName, attContext string) (*lakala.AttachmentImgResp, error) {
	parameter := &lakala.AttachmentImg{
		Version:    "1.0",
		OrderNo:    lakala.GetOrderNumber(8),
		OrgCode:    orgCode,
		AttType:    attType,
		AttExtName: attExtName,
		AttContext: attContext,
	}
	//base64DecryData, _ := base64.StdEncoding.DecodeString(attContext)

	return api.LaKaLaApi.AttachmentUpload(parameter)
}

//#endregion

//#region京西数据查询

// GetIncomingList 进件查询
func GetIncomingList(merchantNo string, storeId, pageSize, offset int) (*model.PagedInfo, error) {
	return dao.GetIncoming(storeId, merchantNo, offset, pageSize)
}

// GetRecipientList 获取分账商户
func GetRecipientList(orgCode, receiverNo, receiverName string, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) {
	return dao.GetRecipientList(orgCode, receiverNo, receiverName, offset, pageSize)
}

// GetSeparateAmt 分账流水查询
func GetSeparateAmt(merchantNo, cmdType, status, separateNo, separateTimeStart, separateTimeEnd, vendorOrderID string, storeId int, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) {
	var (
		start time.Time
		end   time.Time
	)
	if separateTimeStart != "" {
		start = utils.Str2Time(separateTimeStart)
	}
	if separateTimeEnd != "" {
		end = utils.Str2Time(separateTimeEnd)
	}
	return dao.GetSeparateAmt(merchantNo, cmdType, status, separateNo, vendorOrderID, storeId, start, end, offset, pageSize)
}

// WithdrawalList 提现流水查询
func WithdrawalList(merchantNo, drawJnl, acctName, startTime, endTime string, pageSize, offset int) (pagedInfo *model.PagedInfo, err error) {
	var (
		start time.Time
		end   time.Time
	)
	if startTime != "" {
		start = utils.Str2Time(startTime)
	}
	if endTime != "" {
		end = utils.Str2Time(endTime)
	}
	return dao.WithdrawalList(merchantNo, drawJnl, acctName, start, end, pageSize, offset)
}

// QueryApplyContractList 门店合同申请记录
func QueryApplyContractList(orderNo string, storeID, pageSize, offset int) (pagedInfo *model.PagedInfo, err error) {
	return dao.QueryApplyContractList(orderNo, storeID, pageSize, offset)
}

//#endregion
