package com.hzs.third.pay.service.impl;

import cn.hutool.json.JSONUtil;
import com.huifu.bspay.sdk.opps.client.BasePayClient;
import com.huifu.bspay.sdk.opps.core.request.V2TradePaymentScanpayRefundRequest;
import com.huifu.bspay.sdk.opps.core.request.V2TradePaymentScanpayRefundqueryRequest;
import com.huifu.bspay.sdk.opps.core.utils.DateTools;
import com.hzs.common.core.constant.MagicNumberConstants;
import com.hzs.common.core.domain.R;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.utils.*;
import com.hzs.common.domain.third.pay.TOnlinePayment;
import com.hzs.common.domain.third.pay.TOnlineRefund;
import com.hzs.common.domain.third.pay.ext.TOnlineRefundExt;
import com.hzs.sale.refund.ISaRefundServiceApi;
import com.hzs.third.pay.config.HuiFuConfig;
import com.hzs.third.pay.constants.HuiFuPayConstants;
import com.hzs.third.pay.service.IRefundService;
import com.hzs.third.pay.service.ITOnlineRefundService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;

/**
 * @Description: 基础退款服务
 * @Author: jiang chao
 * @Time: 2023/8/16 17:00
 * @Classname: RefundServiceImpl
 * @PackageName: com.hzs.third.pay.service.impl
 */
@Slf4j
@Service
public class RefundServiceImpl implements IRefundService {

    @Autowired
    private HuiFuConfig huiFuConfig;
    @Autowired
    private ITOnlineRefundService itOnlineRefundService;

    @DubboReference
    ISaRefundServiceApi iSaRefundServiceApi;

    @Override
    public String huifuRefundHandle(TOnlinePayment tOnlinePayment) {
        // 返回信息
        String returnStr = null;
        try {
            // 退款单号
            String refundCode = CommonUtil.createSerialNumber(EOrderPrefix.REFUND_CODE);
            // 保存退款信息
            TOnlineRefund tOnlineRefund = TOnlineRefund.builder()
                    .refundCode(refundCode)
                    .businessCode(tOnlinePayment.getBusinessCode())
                    .refundStatus(ERefundStatus.REFUND_REQUEST.getValue())
                    .refundMoney(tOnlinePayment.getPayMoney())
                    .refundChannel(tOnlinePayment.getPayChannel())
                    .pkOnlinePayment(tOnlinePayment.getPkId())
                    .build();
            tOnlineRefund.setPkCreator(MagicNumberConstants.PK_ADMIN);
            tOnlineRefund.setPkCountry(tOnlinePayment.getPkCountry());
            itOnlineRefundService.save(tOnlineRefund);

            // 组装交易参数
            V2TradePaymentScanpayRefundRequest request = new V2TradePaymentScanpayRefundRequest();
            // 请求日期
            request.setReqDate(DateTools.getCurrentDateYYYYMMDD());
            // 请求流水号（保证唯一）
            request.setReqSeqId(refundCode);
            // 商户号
            request.setHuifuId(huiFuConfig.getSysId());
            // 申请退款金额
            request.setOrdAmt(new DecimalFormat("#0.00").format(tOnlinePayment.getPayMoney()));
            // 原交易请求日期
            request.setOrgReqDate(DateTools.dateToDateString(tOnlinePayment.getCreationTime(), DateTools.DATE_YYYYMMDD));
            // 设置非必填字段
            Map<String, Object> extendInfoMap = new HashMap<>();
            // 原交易流水号
            extendInfoMap.put("org_hf_seq_id", tOnlinePayment.getPayNumber());
            // 追加参数
            request.setExtendInfo(extendInfoMap);

            log.info("新汇付退款调用参数：{}", JSONUtil.toJsonStr(request));

            Map<String, Object> response = BasePayClient.request(request);

            log.info("新汇付退款调用返回：{}", JSONUtil.toJsonStr(response));

            tOnlineRefund.setRefundNumber(response.get("hf_seq_id").toString());
            if (HuiFuPayConstants.TRANS_SUCCESS.equals(response.get("trans_stat").toString())) {
                // 处理成功
                tOnlineRefund.setRefundStatus(ERefundStatus.REFUNDED.getValue());
                tOnlineRefund.setFinishTime(DateUtils.parseDateOne(response.get("trans_finish_time"), DateUtils.YAMMERERS));
                if (null != response.get("actual_ref_amt")) {
                    tOnlineRefund.setFinishMoney(new BigDecimal(response.get("actual_ref_amt").toString()));
                }
            } else if (HuiFuPayConstants.TRANS_PROCESSING.equals(response.get("trans_stat").toString())) {
                // 处理中
                tOnlineRefund.setRefundStatus(ERefundStatus.REFUNDING.getValue());
            } else {
                // 退款失败
                tOnlineRefund.setRefundStatus(ERefundStatus.REFUND_FAILED.getValue());
                tOnlineRefund.setErrorMsg(response.get("resp_desc").toString());

                log.error("新汇付退款交易失败! resp_desc: {}, bank_message: {}, hf_seq_id: {}", response.get("resp_desc"), response.get("bank_message"), response.get("hf_seq_id"));
                returnStr = "新汇付退款交易失败";
            }

            // 更新接口返回状态
            itOnlineRefundService.updateById(tOnlineRefund);
        } catch (Exception e) {
            log.error("新汇付退款处理异常", e);
            returnStr = "新汇付退款处理异常：" + e.getMessage();
        }
        return returnStr;
    }

    @Override
    public String queryHuifuRefundHandle(TOnlineRefund tOnlineRefund) {
        try {
            V2TradePaymentScanpayRefundqueryRequest request = new V2TradePaymentScanpayRefundqueryRequest();

            // 商户号
            request.setHuifuId(huiFuConfig.getSysId());
            // 退款请求日期
            request.setOrgReqDate(DateTools.dateToDateString(tOnlineRefund.getCreationTime(), DateTools.DATE_YYYYMMDD));
            // 退款全局流水号退款请求流水号,退款全局流水号,终端订单号三选一不能都为空
            request.setOrgHfSeqId(tOnlineRefund.getRefundNumber());

            log.info("新汇付退款查询调用参数：{}", JSONUtil.toJsonStr(request));

            Map<String, Object> response = BasePayClient.request(request);

            log.info("新汇付退款查询调用返回：{}", JSONUtil.toJsonStr(response));

            if (HuiFuPayConstants.TRANS_SUCCESS.equals(response.get("trans_stat").toString())) {
                // 处理成功
                tOnlineRefund.setRefundStatus(ERefundStatus.REFUNDED.getValue());
                tOnlineRefund.setFinishTime(DateUtils.parseDateOne(response.get("trans_finish_time"), DateUtils.YAMMERERS));
                if (null != response.get("actual_ref_amt")) {
                    tOnlineRefund.setFinishMoney(new BigDecimal(response.get("actual_ref_amt").toString()));
                }
            } else if (HuiFuPayConstants.TRANS_PROCESSING.equals(response.get("trans_stat").toString())) {
                // 处理中
                tOnlineRefund.setRefundStatus(ERefundStatus.REFUNDING.getValue());
            } else if (HuiFuPayConstants.TRANS_FAIL.equals(response.get("trans_stat").toString())) {
                // 退款失败
                tOnlineRefund.setRefundStatus(ERefundStatus.REFUND_FAILED.getValue());
                tOnlineRefund.setErrorMsg(response.get("resp_desc").toString());
            } else {
                return "新汇付退款查询状态：初始化，需要联系汇付技术人员处理";
            }

            return null;
        } catch (Exception e) {
            log.error("新汇付退款查询处理异常", e);
            return "新汇付退款查询处理异常：" + e.getMessage();
        }
    }

    @Override
    public boolean notifyHandle(EPayChannel ePayChannel, String refundCode, String refundNumber, Date finishTime, BigDecimal finishMoney) {
        try {
            // 查询退款信息
            TOnlineRefundExt onlineRefund = this.queryOnlineRefund(refundCode, ePayChannel, refundNumber);
            if (null == onlineRefund || ERefundStatus.REFUNDED.getValue() == onlineRefund.getRefundStatus()) {
                log.error("退款回调成功: 信息不存在或已退款");
                return false;
            }

            if (onlineRefund.getRefundMoney().compareTo(finishMoney) > 0) {
                // 退款金额 大于 退款到账金额
                log.warn("退款回调成功: 退款金额大于退款到账金额，退款编号：{}, 退款到账金额：{}", onlineRefund.getRefundCode(), finishMoney);
            }

            // 更新退款信息（退款成功）
            onlineRefund.setRefundStatus(ERefundStatus.REFUNDED.getValue());
            onlineRefund.setRefundNumber(refundNumber);
            onlineRefund.setFinishTime(finishTime);
            onlineRefund.setFinishMoney(finishMoney);
            onlineRefund.setErrorMsg("");
            // 更新退款相关信息
            if (itOnlineRefundService.updateById(onlineRefund)) {

                // 退款业务处理
                if (StringUtils.isNotEmpty(onlineRefund.getPayBusinessCode())) {
                    // 如果退款业务单号存在则进行业务回调处理，如果不存在则表示直接根据支付信息进行退款，不需要进行业务回调

                    if (this.handleBusiness(onlineRefund)) {
                        // 更新业务处理信息
                        if (itOnlineRefundService.updateById(onlineRefund)) {
                            return true;
                        }
                    }
                }
                return true;
            }
        } catch (Exception e) {
            log.error("退款回调成功: 处理异常", e);
        }
        return false;
    }

    @Override
    public boolean notifyErrorHandle(EPayChannel ePayChannel, String refundCode, String refundNumber, String errorMsg) {
        try {
            // 查询退款信息
            TOnlineRefundExt onlineRefund = this.queryOnlineRefund(refundCode, ePayChannel, refundNumber);
            if (null == onlineRefund || ERefundStatus.REFUNDED.getValue() == onlineRefund.getRefundStatus()) {
                log.error("退款回调失败: 信息不存在或已退款");
                return false;
            }

            // 更新退款信息（退款失败）
            onlineRefund.setRefundStatus(ERefundStatus.REFUND_FAILED.getValue());
            onlineRefund.setRefundNumber(refundNumber);
            onlineRefund.setErrorMsg(errorMsg);
            if (itOnlineRefundService.updateById(onlineRefund)) {
                // 退款业务处理
                if (StringUtils.isNotEmpty(onlineRefund.getBusinessCode())) {
                    // 如果退款业务单号存在则进行业务回调处理，如果不存在则表示直接根据支付信息进行退款，不需要进行业务回调
                    if (this.handleBusiness(onlineRefund)) {
                        // 更新业务处理信息
                        if (itOnlineRefundService.updateById(onlineRefund)) {
                            return true;
                        }
                    }
                }
                return true;
            }
        } catch (Exception e) {
            log.error("退款回调失败: 处理异常", e);
        }
        return false;
    }

    /**
     * 查询退款信息
     *
     * @param refundCode   退款编号
     * @param ePayChannel  退款渠道
     * @param refundNumber 退款流水号
     * @return
     */
    private TOnlineRefundExt queryOnlineRefund(String refundCode, EPayChannel ePayChannel, String refundNumber) {
        // 获取退款信息
        if (StringUtils.isNotEmpty(refundCode)) {
            return itOnlineRefundService.queryRefundAndPay(refundCode, null, null);
        } else {
            return itOnlineRefundService.queryRefundAndPay(null, ePayChannel.getValue(), refundNumber);
        }
    }

    /**
     * 退款业务处理
     *
     * @param onlineRefund 退款数据
     * @return
     */
    private boolean handleBusiness(TOnlineRefundExt onlineRefund) {
        // 业务类型
        EPayBusinessType businessType = EPayBusinessType.getEnumByValue(onlineRefund.getPayBusinessType());
        if (null != businessType) {
            // 服务调用结果
            Boolean resultBool = null;
            // 服务调用返回信息
            String resultMsg = "";
            // 根据业务类型调用具体业务处理 dubbo 服务
            switch (businessType) {
                case MEMBER_ORDER:
                    // 会员订单
                    R<String> saRefundR = iSaRefundServiceApi.onlinePayRefundCallback(onlineRefund.getPayBusinessCode(), onlineRefund.getBusinessCode(), onlineRefund.getRefundStatus(), onlineRefund.getErrorMsg());
                    if (saRefundR.isSuccess()) {
                        resultBool = true;
                    } else {
                        resultBool = false;
                        resultMsg = saRefundR.getMsg();
                    }
                    break;
                default:
            }

            if (null != resultBool) {
                if (resultBool) {
                    // 调用业务处理成功、失败，如果失败记录原因
                    onlineRefund.setCallbackStatus(ECallbackStatus.SUCCESS.getValue());
                    onlineRefund.setCallbackInfo("");
                } else {
                    onlineRefund.setCallbackStatus(ECallbackStatus.FAIL.getValue());
                    onlineRefund.setCallbackInfo(resultMsg);
                }
            } else {
                log.error("退款回调没有后续业务处理");
                onlineRefund.setCallbackInfo("退款回调没有后续业务处理");
            }
            return true;

        }
        log.error("退款业务处理失败，不存在的业务类型");
        return false;
    }

}
