package com.qs.mp.pay.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.qs.mp.channel.service.IChannelOrderService;
import com.qs.mp.common.enums.AsyncTaskTypeEnum;
import com.qs.mp.common.enums.BizTypeEnum;
import com.qs.mp.common.enums.MqTopicType;
import com.qs.mp.common.enums.PayOrderStatusEnum;
import com.qs.mp.common.exception.ServiceException;
import com.qs.mp.common.pulsar.PulsarClientService;
import com.qs.mp.common.utils.DateUtils;
import com.qs.mp.common.utils.LogUtil;
import com.qs.mp.common.utils.StringUtils;
import com.qs.mp.common.utils.http.OkHttpUtil;
import com.qs.mp.framework.domain.AsyncTask;
import com.qs.mp.framework.service.IAsyncTaskService;
import com.qs.mp.pay.domain.PayOrder;
import com.qs.mp.pay.service.IPayOrderService;
import com.qs.mp.pay.service.IWalletService;
import com.qs.mp.system.service.id.BizIdGenerator;
import com.qs.mp.user.service.IUserDeliverOrderService;
import com.qs.mp.user.service.IUserTicketOrderService;
import org.apache.pulsar.client.api.PulsarClientException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Objects;

/**
 * @auther duota
 * @create 2021 2021/9/4 1:59 下午
 * @describe
 */
@Service
public class WalletServiceImpl implements IWalletService {

  protected final Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName());

  @Autowired
  private IPayOrderService payOrderService;

  @Autowired
  private IChannelOrderService channelOrderService;

  @Autowired
  private IUserTicketOrderService userTicketOrderService;

  @Autowired
  private IUserDeliverOrderService userDeliverOrderService;

  @Autowired
  private PulsarClientService pulsarClientService;

  @Autowired
  private BizIdGenerator bizIdGenerator;

  @Autowired
  private IAsyncTaskService asyncTaskService;

  @Value("${pay.notifyUrl}")
  private String notifyUrl;  //支付成功前端跳转地址
  @Value("${pay.callbackUrl}")
  private String callbackUrl;  //支付回调地址
  @Value("${pay.baseUrl}")
  private String baseUrl;
  @Value("${wx-channel.appId}")
  private String channelAppId;
  @Value("${wx-user.appId}")
  private String userAppId;

  @Value("${pay.user-shopNo}")
  private String userPayShopNo;  //用户端商户号
  @Value("${pay.user-sign}")
  private String userPaySign;  //用户端商户签名

  @Value("${pay.channel-shopNo}")
  private String channelPayShopNo;  //渠道端商户号
  @Value("${pay.channel-sign}")
  private String channelPaySign;  //渠道端商户签名

  private static final String REQ_STATUS_SUCCESS = "R0001";
  private static final String PAY_RESOURCE = "2"; //2:微信支付
  private static final String PAY_RESOURCE_TYPE = "1017"; //2:微信小程序

  @Override
  public JSONObject pay(BizTypeEnum bizType, String bizId, String openId, int money,
      String orderRemark) {
    String reqUrl = baseUrl + "/pay/payMoneyCTB";
    String appId = channelAppId;
    String payShopNo = channelPayShopNo;
    String paySign = channelPaySign;
    if (bizType == BizTypeEnum.TICKET_ORDER || bizType == BizTypeEnum.DELIVER_ORDER) {
      appId = userAppId;
      payShopNo = userPayShopNo;
      paySign = userPaySign;
    }
    JSONObject params = buildPayOrderReqData(payShopNo, paySign, money, openId, appId, orderRemark);
    String result = OkHttpUtil.postJsonParams(reqUrl, params.toJSONString());
    logger.info("request params:" + params.toJSONString() + "  result:" + result);
    if (StringUtils.isBlank(result)) {
      LogUtil.error(logger, "创建支付订单接口失败");
      throw new ServiceException("创建三方支付订单失败");
    }
    JSONObject resultJson = JSONObject.parseObject(result);
    String code = resultJson.getString("code");
    String orderNo = resultJson.getString("order_no");
    JSONObject data = resultJson.getJSONObject("pay_info");
    String orderstatus = resultJson.getString("orderstatus");
    String resultMsg = resultJson.getString("result");
    if (!REQ_STATUS_SUCCESS.equalsIgnoreCase(code)) {
      throw new ServiceException(resultMsg);
    }
    //保存订单记录
    PayOrder payOrder = buildPayOrder(params);
    payOrder.setOrderId(resultJson.getString("shop_order_no"));
    payOrder.setOrderNo(orderNo);
    payOrder.setCode(code);
    payOrder.setBizType(bizType);
    payOrder.setBizId(bizId);
    payOrder.setOrderStatus(orderstatus);
    boolean ret = payOrderService.save(payOrder);
    if (!ret) {
      LogUtil.error(logger, "支付订单数据库保存失败.");
      throw new ServiceException("支付订单保存失败");
    }
    return data;

  }

  @Override
  public boolean refund(String bizId, Integer refundAmount, String remark) {
    // 获取支付成功的订单号
    PayOrder payOrder = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>()
            .eq(PayOrder::getBizId, bizId)
            .eq(PayOrder::getOrderStatus, PayOrderStatusEnum.SUCCESS));
    if (Objects.isNull(payOrder)) {
      throw new ServiceException("支付订单不存在");
    }

    String reqUrl = baseUrl + "/pay/refundOrder";
    JSONObject sendData = new JSONObject();

    if (BizTypeEnum.CHANNEL_ORDER.equals(payOrder.getBizType())) {
      sendData.put("shop_no", channelPayShopNo);
      sendData.put("sign",channelPaySign);
    } else {
      sendData.put("shop_no", userPayShopNo);
      sendData.put("sign",userPaySign);
    }
    sendData.put("timestamp",System.currentTimeMillis());
    sendData.put("order_no",payOrder.getOrderId());
    sendData.put("refund_amount", refundAmount);
    sendData.put("order_remark", remark);
    sendData.put("type","sno");
    String result = OkHttpUtil.postJsonParams(reqUrl, sendData.toJSONString());
    JSONObject jsonObject = JSONObject.parseObject(result);
    String code = jsonObject.getString("code");
    logger.info("用户订单退款 -> request params:" + sendData.toJSONString() + "  result:" + result);
    // 退款成功,更新订单状态
    if ("R0001".equals(code)) {
      boolean ret = payOrderService.update(new LambdaUpdateWrapper<PayOrder>()
              .set(PayOrder::getOrderStatus, PayOrderStatusEnum.REFUND.getValue())
              .eq(PayOrder::getOrderId, payOrder.getOrderId())
              .eq(PayOrder::getOrderStatus, PayOrderStatusEnum.SUCCESS.getValue()));

      if (!ret) {
        LogUtil.error(logger, "订单退款状态数据库更新失败, BizId:" + bizId);
      }
      return true;
    }
    LogUtil.error(logger, "订单退款失败,code:" + code);
    throw new ServiceException("订单退款失败");
  }


  @Override
  public void payOrderStatusHandle(PayOrder payOrder) {
    String orderNo = payOrder.getOrderId();

    //查询统一支付订单表，查询订单类型，然后根据不同类型做对应的逻辑处理
    //查询支付状态为1：支付成功，2：订单创建成功，等待支付。
    PayOrder order = payOrderService.getById(orderNo);
    LogUtil.info(logger, "支付回调,bizType:{0},bizId:{1}" ,
        new Object[]{order.getBizType(), order.getBizId()});
    if (BizTypeEnum.CHANNEL_ORDER == order.getBizType()) {
      // 渠道盲票采购订单支付成功，调用业务订单服务处理
      channelOrderService.paySuccess(order);
    } else if (BizTypeEnum.TICKET_ORDER == order.getBizType()) {
      // 用户盲票购买订单支付成功，调用业务订单服务处理
      userTicketOrderService.paySuccess(order);
    } else if (BizTypeEnum.DELIVER_ORDER == order.getBizType()) {
      // 用户提货订单支付成功，调用业务订单服务处理
      userDeliverOrderService.paySuccess(order);
    } else {
      //数据结构异常，告警
      LogUtil.error(logger, "该业务单据类型未支持，orderNo：" + orderNo);
      throw new ServiceException("该业务单据类型未支持，orderNo：" + orderNo);
    }
  }


  @Override
  public boolean drawings(String merchId, int money) {
    return false;
  }

  @Override
  public boolean drawingsApply(String merchId, int money) {
    return false;
  }

  @Override
  public boolean completeDrawingsApply(String merchId) {
    return false;
  }


  private PayOrder buildPayOrder(JSONObject jsonObject) {
    PayOrder payOrder = jsonObject.toJavaObject(PayOrder.class);
    return payOrder;
  }

  private JSONObject buildPayOrderReqData(String shopNo, String sign, int money, String openId, String appId, String orderRemark) {

    JSONObject sendData = new JSONObject();
    sendData.put("shop_no" , shopNo);
    sendData.put("shop_order_no" , String.valueOf(bizIdGenerator.newId()));
    sendData.put("shop_order_time" , DateUtils.getTime());
    sendData.put("pay_resource" , PAY_RESOURCE); //支付来源 1:支付宝  2:微信支付 5：云闪付
    sendData.put("trans_type_code" , PAY_RESOURCE_TYPE); //1017：微信小程序
    sendData.put("transaction_amount" , money);
    sendData.put("order_remark" , "");
    sendData.put("timestamp" , System.currentTimeMillis());
    sendData.put("callback_url" , callbackUrl);
    // 截取备注长度
    sendData.put("orderName" , StringUtils.isNotBlank(orderRemark) && orderRemark.length() > 10 ? orderRemark.substring(0, 10) : orderRemark);
    sendData.put("sign" , sign);
    sendData.put("client_ip" , "113.31.163.91");

    sendData.put("auth_code" , openId);
    sendData.put("notify_url" , notifyUrl);
    sendData.put("app_id" , appId);
    return sendData;
  }
}
