package com.fs.store.service.channel;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.fs.common.core.domain.R;
import com.fs.common.exception.CustomException;
import com.fs.common.utils.IPUtils;
import com.fs.common.utils.ServletUtils;
import com.fs.huifuPay.dto.*;
import com.fs.store.config.StoreConfig;
import com.fs.store.domain.FsStorePayment;
import com.fs.store.domain.TzConfigInfoDTO;
import com.fs.store.service.IFsCouponScheduleService;
import com.fs.store.service.channel.param.PayProcessContext;
import com.fs.store.service.impl.FsCouponScheduleServiceImpl;
import com.fs.system.service.ISysConfigService;
import com.fs.tzBank.TzBankService;
import com.fs.tzBank.utils.TzConfigUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.Date;

import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE;

/**
 * tzbk支付处理
 */
@Service
@Slf4j
@Scope(value = SCOPE_PROTOTYPE)
public class TzbkPaymentHandler extends PaymentHandler{


    @Autowired
    private ISysConfigService configService;
    @Autowired
    private TzBankService tzBankService;
    @Autowired
    private IFsCouponScheduleService fsCouponScheduleService;


    @Override
    protected R doCreateOrder(PayProcessContext context) {
        String json = configService.selectConfigByKey("store.pay");
        String configJson=configService.selectConfigByKey("store.config");
        StoreConfig config= JSONUtil.toBean(configJson,StoreConfig.class);
        TzConfigInfoDTO tzConfigInfoDTO = JSON.parseObject(json, TzConfigInfoDTO.class);

        TzPayCreateOrderReqBodyDTO reqBodyDTO = new TzPayCreateOrderReqBodyDTO();
        RequestDTO<TzPayCreateOrderReqBodyDTO> requestDTO = new RequestDTO<>();
        reqBodyDTO.setOrderNo(String.valueOf(context.getPayCode()));
        reqBodyDTO.setOrderSource("02");
        reqBodyDTO.setTrxAmt(this.fsStorePayment.getPayMoney());
        reqBodyDTO.setCurrency("CNY");
        reqBodyDTO.setTransType("2001");
        reqBodyDTO.setTradeMerCstNo(tzConfigInfoDTO.getPlatMerCstNo());
        reqBodyDTO.setPlatMerCstNo(tzConfigInfoDTO.getPlatMerCstNo());
        reqBodyDTO.setBusinessCstNo(user.getUserId().toString());
        reqBodyDTO.setPayNotifyUrl(tzConfigInfoDTO.getPayNotifyUrl());
        reqBodyDTO.setPayerName(user.getUsername());
        reqBodyDTO.setPayerMobileNo(user.getPhone());
        reqBodyDTO.setGoodsInfo(context.getGoodsInfo());
        // 不需要分账
        reqBodyDTO.setNeedLedger("00");
        reqBodyDTO.setClientIp(IPUtils.getIpAddr(ServletUtils.getRequest()));

        // 获取当前时间戳
        Instant currentTimestamp = Instant.now();
        Integer unPayTime = config.getUnPayTime();
        if(ObjectUtil.isNull(unPayTime)){
            unPayTime = 1800;
        }
        Instant oneHourLater = currentTimestamp.plusSeconds(unPayTime*60L);
        reqBodyDTO.setExpiredTime(String.valueOf(oneHourLater.toEpochMilli()));


        requestDTO.setReqHeader(TzReqHeaderDTO.getInstance(context.getPayCode()));
        requestDTO.setReqBody(reqBodyDTO);
        try {
            // 创建订单
            TzReqResultDTO<TzPayCreateOrderRspDTO> payCreateOrder = tzBankService.payCreateOrder(requestDTO);
            // 获得小程序请求码
            if("00000000".equals(payCreateOrder.getRetCode())){
                TzPayCreateOrderRspDTO body = payCreateOrder.getBody();

                RequestDTO<TzMiniProgramCodeReqDTO> reqDTORequestDTO = new RequestDTO<>();
                TzMiniProgramCodeReqDTO tzMiniProgramCodeReqDTO = new TzMiniProgramCodeReqDTO();
                tzMiniProgramCodeReqDTO.setOrderNo(body.getOrderFlowNo());
                tzMiniProgramCodeReqDTO.setPlatMerCstNo(tzConfigInfoDTO.getPlatMerCstNo());
                tzMiniProgramCodeReqDTO.setBusinessCstNo(user.getUserId().toString());
                reqDTORequestDTO.setReqHeader(TzReqHeaderDTO.getInstance(context.getPayCode()));
                reqDTORequestDTO.setReqBody(tzMiniProgramCodeReqDTO);
                TzReqResultDTO<TzMiniProgramCodeRespDTO> miniProgramCode = tzBankService.miniProgramCode(reqDTORequestDTO);
                if("00000000".equals(miniProgramCode.getRetCode())){
                    FsStorePayment mt=new FsStorePayment();
                    mt.setPaymentId(context.getPaymentId());
                    mt.setTradeNo(miniProgramCode.getBody().getOrderNo());
                    this.fsStorePaymentService.updateFsStorePayment(mt);
                    TzMiniProgramCodeRespDTO result = miniProgramCode.getBody();
                    result.setPayCode(context.getPayCode());
                    return R.ok().put("payType",context.getPayType()).put("result",result);
                } else {
                    return R.error(miniProgramCode.getRetMsg());
                }
            } else {
                return R.error(payCreateOrder.getRetMsg());
            }
        } catch (Throwable e) {
            log.error("系统异常",e);
            return R.error("系统异常，请联系管理员!");
        }
    }

    @Override
    protected void doRefundOrder(PayProcessContext context) {
        TzConfigInfoDTO tzConfigInfoDTO = TzConfigUtils.getConfig();

        RequestDTO<TzPayRefundDTO> requestDTO = new RequestDTO<>();
        TzPayRefundDTO tzPayRefundDTO = new TzPayRefundDTO();
        tzPayRefundDTO.setOldPayOutOrderNo(fsStorePayment.getPayCode());
        tzPayRefundDTO.setRefundOrderNo(fsStorePayment.getPayCode());
        tzPayRefundDTO.setPlatMerCstNo(tzConfigInfoDTO.getPlatMerCstNo());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        tzPayRefundDTO.setTrxSendTime(sdf.format(new Date()));
        tzPayRefundDTO.setRefundOrdTransAmt(fsStorePayment.getPayMoney());
        tzPayRefundDTO.setNotifyURL(tzConfigInfoDTO.getRefundNotifyUrl());
        requestDTO.setReqBody(tzPayRefundDTO);
        requestDTO.setReqHeader(TzReqHeaderDTO.getInstance(fsStorePayment.getPayCode()));

        TzReqResultDTO<TzRefundNotifyDTO> resultDTO;

        try {

            // 停止发放优惠券
            if(ObjectUtil.isNotNull(order)){
                fsCouponScheduleService.setScheduleCouponRefund(String.valueOf(order.getId()));
            }

            resultDTO = tzBankService.payRefund(requestDTO);

            TzRefundNotifyDTO body = resultDTO.getBody();
            String refundOrdStatus = body.getRefundOrdStatus();
            if("90".equals(refundOrdStatus) || "50".equals(refundOrdStatus)){
                fsStorePayment.setRefundMoney(fsStorePayment.getPayMoney());
                fsStorePayment.setStatus(-1);
                fsStorePayment.setRefundTime(new Date());
                this.fsStorePaymentService.updateFsStorePayment(fsStorePayment);
            } else {
                throw new CustomException(resultDTO.getRetMsg());
            }
        } catch (Exception e) {
            throw new RuntimeException("退款请求失败"+e);
        }
    }

    @Override
    public boolean support(String code) {
        return "tzbk".equals(code);
    }
}
