package com.liquidnet.service.dragon.channel.strategy.impl;

import com.alibaba.fastjson.JSON;
import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.commons.lang.util.StringUtil;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.biz.DragonServiceCommonBiz;
import com.liquidnet.service.dragon.channel.strategy.annotation.StrategyPayChannelHandler;
import com.liquidnet.service.dragon.channel.strategy.biz.DragonPayBiz;
import com.liquidnet.service.dragon.channel.unionpay.biz.UnionpayBiz;
import com.liquidnet.service.dragon.channel.unionpay.sdk.AcpService;
import com.liquidnet.service.dragon.channel.unionpay.sdk.SDKConstants;
import com.liquidnet.service.dragon.channel.unionpay.strategy.UnionpayStrategyContext;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.constant.DragonErrorCodeEnum;
import com.liquidnet.service.dragon.dto.DragonOrdersDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import com.liquidnet.service.dragon.service.impl.DragonOrderRefundsServiceImpl;
import com.liquidnet.service.dragon.utils.DataUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Map;

/**
 * @author AnJiabin <anjiabin@zhengzai.tv>
 * @version V1.0
 * @Description: TODO
 * @class: PayChannelStrategyUnionpayImpl
 * @Package com.liquidnet.service.dragon.channel.strategy.impl
 * @Copyright: LightNet @ Copyright (c) 2021
 * @date 2021/11/08 18:06
 */
@Slf4j
@Component
@StrategyPayChannelHandler(DragonConstant.PayChannelEnum.UNIONPAY)
public class PayChannelStrategyUnionpayImpl extends AbstractPayChannelStrategyImpl {
    @Autowired
    private UnionpayStrategyContext unionpayStrategyContext;

    @Autowired
    private DataUtils dataUtils;

    @Autowired
    private UnionpayBiz unionpayBiz;

    @Autowired
    private DragonPayBiz dragonPayBiz;

    @Autowired
    private DragonServiceCommonBiz dragonServiceCommonBiz;

    @Autowired
    private DragonOrderRefundsServiceImpl dragonOrderRefundsService;
    @Autowired
    private AcpService acpService;

    @Override
    public ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto) {
        return unionpayStrategyContext.getStrategy(dragonPayBaseReqDto.getDeviceFrom()).dragonPay(dragonPayBaseReqDto);
    }

    @Override
    public String dragonNotify(HttpServletRequest request,String payType,String deviceFrom) {
        log.info("unionpay-->notify-->begin payType:{} deviceFrom:{}",payType,deviceFrom);
        try {
            String encoding = request.getParameter(SDKConstants.param_encoding);
            Map<String , String> notifyMap = unionpayBiz.parseNotifyMsg(request);
            log.info("dragonNotify-->unionpay json : {}", JSON.toJSONString(notifyMap));
            log.info("接收到{}支付结果{}", payType, notifyMap);
            //商户订单号
            String code =notifyMap.get("orderId"); //获取后台通知的数据
            if(StringUtil.isBlank(code)){
                throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getCode(),DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getMessage());
            }
            //持久化通知记录
            dragonServiceCommonBiz.createDragonOrderLogs(code,dragonPayBiz.getPaymentType(payType,deviceFrom),JSON.toJSONString(notifyMap));
            // 根据银行订单号获取支付信息
            DragonOrdersDto dragonOrdersDto = dataUtils.getPayOrderByCode(code);
            if (dragonOrdersDto == null) {
                throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getCode(),DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getMessage());
            }
            if (DragonConstant.PayStatusEnum.STATUS_PAID.getCode().equals(dragonOrdersDto.getStatus())) {
                throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_HAS_PAID.getCode(),DragonErrorCodeEnum.TRADE_ERROR_HAS_PAID.getMessage());
            }
            boolean notifyResult = false;
            //1、验证签名
            if (acpService.validate(notifyMap, encoding)) {
                //判断respCode=00、A6后，对涉及资金类的交易，请再发起查询接口查询，确定交易成功后更新数据库。
                //因发现00 是成功 a6为有缺陷的成功，所以如果是a6则要再查一下
                boolean result=false;
                if(notifyMap.get("respCode").equals("A6")){
                    //此处需要发起查询接口，要看下最终状态，等查询接口完毕后再写
                    result=true;
                }else if (notifyMap.get("respCode").equals("00")){
                    result =true;
                }else{
                    result =false;

                }
                if(result){
                    notifyResult = this.completeSuccessOrder(dragonOrdersDto, notifyMap.get("queryId"), LocalDateTime.now(), notifyMap.toString());
                }else{
                    notifyResult = this.completeFailOrder(dragonOrdersDto, notifyMap.toString());
                }

            }else{
                log.error("unionPay notify fail code:{} msg:{} ",DragonErrorCodeEnum.TRADE_UNIONPAY_SIGN_ERROR.getCode(),DragonErrorCodeEnum.TRADE_UNIONPAY_SIGN_ERROR.getMessage());
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return "ok";
    }

    @Override
    public DragonPayOrderQueryRespDto checkOrderStatus(String code) {
        // 查看是哪个deviceForm  的支付
        DragonOrdersDto ordersDto = dataUtils.getPayOrderByCode(code);

        DragonPayOrderQueryRespDto respDto = unionpayStrategyContext.getStrategy(DragonConstant.PayTypeEnum.getEnumByCode(ordersDto.getPaymentType()).getDeviceFrom()).checkOrderStatus(code);
       /* if(null==ordersDto){
            throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_UNIONPAY_QUERY_ERROR.getCode(),DragonErrorCodeEnum.TRADE_UNIONPAY_QUERY_ERROR.getMessage());
        }
        DragonPayOrderQueryRespDto respDto = dragonPayBiz.buildPayOrderQueryRespDto(ordersDto);
*/
        return respDto;
    }
}
