package com.zhongshu.card.server.core.service.pay;

import com.github.microservice.core.util.JsonUtil;
import com.github.microservice.core.util.bean.BeanUtil;
import com.github.microservice.net.ResultContent;
import com.github.microservice.pay.client.model.PayProductParameter;
import com.github.microservice.pay.client.model.ledger.TransactionLogModel;
import com.github.microservice.pay.client.model.ledger.TransferTransactionsModel;
import com.github.microservice.pay.client.model.weChatMiniApp.WeChatMiniAppRefundRet;
import com.github.microservice.pay.client.ret.ResultState;
import com.github.microservice.pay.client.service.ledger.TransactionLogService;
import com.github.microservice.pay.client.service.product.MiniAppPayService;
import com.github.microservice.pay.client.type.ledger.TransactionStatus;
import com.github.microservice.pay.client.type.ledger.TransactionType;
import com.github.microservice.types.payment.PaymentChannelType;
import com.github.microservice.types.payment.PaymentType;
import com.zhongshu.card.client.model.pay.WeChatPrepayParam;
import com.zhongshu.card.client.model.pay.WeChatRefundParam;
import com.zhongshu.card.server.core.domain.pay.PayAccount;
import com.zhongshu.card.server.core.service.base.SuperService;
import com.zhongshu.card.server.core.service.paySetting.OrgPayAccountService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class WechatPayService extends SuperService {

    @Autowired
    MiniAppPayService miniAppPayService;

    @Autowired
    OrgPayAccountService orgPayAccountService;

    @Autowired
    PayAccountService payAccountService;

    @Autowired
    TransactionLogService transactionLogService;

    public ResultContent<Object> prepay(WeChatPrepayParam param) {
        String projectOid = getCurrentProjectOid();
        String userId = getCurrentUserId();
        String appId = getCurrentAppId();

        if (StringUtils.isBlank(projectOid)) {
            return com.github.microservice.net.ResultContent.buildFail("获取项目id失败");
        }

        param.setProjectOid(projectOid);
        param.setUserId(userId);
        param.setAppid(appId);

        //根据项目id和支付渠道获取支付账户名
        String accountName = orgPayAccountService.queryOgPayAccount(param.getOid(), PaymentType.WeChatPay);

        PayProductParameter<Object> payProductParameter = new PayProductParameter<>();
        Map<String, Object> meta = BeanUtil.bean2Map(param);
        payProductParameter.setMeta(meta);
        payProductParameter.setAccountName(accountName);
        com.github.microservice.pay.client.ret.ResultContent<Object> prepay = miniAppPayService.prepay(payProductParameter);
        if (!prepay.getState().equals(ResultState.Success)) {
            return ResultContent.build(com.github.microservice.net.ResultState.Fail, prepay);
        }
        return com.github.microservice.net.ResultContent.buildContent(prepay.getContent());
    }

    public com.github.microservice.pay.client.ret.ResultContent<List<TransactionLogModel>> handleTransactions(String projectOid, String oid, String userId, String orderNo, BigDecimal total) {

        //获取机构待结算账户
        PayAccount orgWaitSettle = payAccountService.getOrgChildren(projectOid, oid, PaymentChannelType.WaitSettle);
        //获取用户余额支付子账
        PayAccount userPayAccount = payAccountService.getUserChildren(projectOid, userId, PaymentChannelType.WeChatMiniPay);
        //构建转账参数

        TransferTransactionsModel transferModel = new TransferTransactionsModel();
        //构建出账账户
        TransferTransactionsModel.GeneralLedgerTransaction sourceTransaction = new TransferTransactionsModel.GeneralLedgerTransaction();
        sourceTransaction.setGeneralLedgerId(userPayAccount.getLedgerId());
        sourceTransaction.setOrderNumber(orderNo);
        sourceTransaction.setTransactionType(TransactionType.WeChatMiniAppPay);
        sourceTransaction.setTransactionStatus(TransactionStatus.Success);
        sourceTransaction.setAmount(total.negate().longValue());
        sourceTransaction.setRemark("微信小程序支付");
        sourceTransaction.setMeta(Map.of("paymentType", PaymentType.WeChat, "description", "微信小程序支付", "summary", "微信小程序支付"));
        transferModel.setSource(new TransferTransactionsModel.GeneralLedgerTransaction[]{sourceTransaction});

        //构建入账账户
        TransferTransactionsModel.GeneralLedgerTransaction destinationTransaction = new TransferTransactionsModel.GeneralLedgerTransaction();
        destinationTransaction.setGeneralLedgerId(orgWaitSettle.getLedgerId());
        destinationTransaction.setOrderNumber(orderNo);
        destinationTransaction.setAmount(total.longValue());
        destinationTransaction.setRemark("微信小程序支付");
        destinationTransaction.setMeta(Map.of("paymentType", PaymentType.WeChat, "description", "微信小程序支付", "summary", "微信小程序支付"));
        transferModel.setDestinations(new TransferTransactionsModel.GeneralLedgerTransaction[]{destinationTransaction});
        return transactionLogService.transfer(transferModel);
    }

    public ResultContent<WeChatMiniAppRefundRet> refund(WeChatRefundParam param) throws Exception {

        //根据项目id和支付渠道获取支付账户名
        String accountName = orgPayAccountService.queryOgPayAccount(param.getOid(), PaymentType.WeChatPay);

        PayProductParameter<Object> payProductParameter = new PayProductParameter<>();
        Map<String, Object> meta = BeanUtil.bean2Map(param);
        payProductParameter.setMeta(meta);
        payProductParameter.setAccountName(accountName);

        com.github.microservice.pay.client.ret.ResultContent<Object> refundResult = miniAppPayService.refund(payProductParameter);
        if (refundResult.getState().equals(ResultState.Success)) {
            WeChatMiniAppRefundRet weChatMiniAppRefundRet = JsonUtil.toObject(JsonUtil.toJson(refundResult.getContent()), WeChatMiniAppRefundRet.class);
            return ResultContent.buildContent(weChatMiniAppRefundRet);
        }
        return ResultContent.buildFail(refundResult.getMsg());
    }

    public com.github.microservice.pay.client.ret.ResultContent<List<TransactionLogModel>> handleRefundTransactions(String projectOid, String oid, String userId, String refundOrderNo, BigDecimal refundTotal) {
        //获取机构待结算账户
        PayAccount orgWaitSettle = payAccountService.getOrgChildren(projectOid, oid, PaymentChannelType.WaitSettle);
        //获取用户余额支付子账
        PayAccount userPayAccount = payAccountService.getUserChildren(projectOid, userId, PaymentChannelType.WeChatMiniPay);
        //构建转账参数

        TransferTransactionsModel transferModel = new TransferTransactionsModel();
        //构建出账账户
        TransferTransactionsModel.GeneralLedgerTransaction sourceTransaction = new TransferTransactionsModel.GeneralLedgerTransaction();
        sourceTransaction.setGeneralLedgerId(orgWaitSettle.getLedgerId());
        sourceTransaction.setOrderNumber(refundOrderNo);
        sourceTransaction.setTransactionType(TransactionType.WeChatMiniAppPay);
        sourceTransaction.setTransactionStatus(TransactionStatus.Success);
        sourceTransaction.setAmount(refundTotal.negate().longValue());
        sourceTransaction.setRemark("微信小程序支付");
        sourceTransaction.setMeta(Map.of("paymentType", PaymentType.WeChat, "description", "微信小程序支付", "summary", "微信小程序支付"));
        transferModel.setSource(new TransferTransactionsModel.GeneralLedgerTransaction[]{sourceTransaction});

        //构建入账账户
        TransferTransactionsModel.GeneralLedgerTransaction destinationTransaction = new TransferTransactionsModel.GeneralLedgerTransaction();
        destinationTransaction.setGeneralLedgerId(userPayAccount.getLedgerId());
        destinationTransaction.setOrderNumber(refundOrderNo);
        destinationTransaction.setAmount(refundTotal.longValue());
        destinationTransaction.setRemark("微信小程序支付");
        destinationTransaction.setMeta(Map.of("paymentType", PaymentType.WeChat, "description", "微信小程序支付", "summary", "微信小程序支付"));
        transferModel.setDestinations(new TransferTransactionsModel.GeneralLedgerTransaction[]{destinationTransaction});
        return transactionLogService.transfer(transferModel);
    }
}
