package com.wteam.framework.modules.book.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeequan.jeepay.Jeepay;
import com.jeequan.jeepay.JeepayClient;
import com.jeequan.jeepay.exception.JeepayException;
import com.jeequan.jeepay.model.PayOrderCreateReqModel;
import com.jeequan.jeepay.model.RefundOrderCreateReqModel;
import com.jeequan.jeepay.request.PayOrderCreateRequest;
import com.jeequan.jeepay.request.RefundOrderCreateRequest;
import com.jeequan.jeepay.response.PayOrderCreateResponse;
import com.jeequan.jeepay.response.RefundOrderCreateResponse;
import com.wteam.framework.common.enums.ResultCode;
import com.wteam.framework.common.enums.ResultUtil;
import com.wteam.framework.common.exception.ServiceException;
import com.wteam.framework.common.security.AuthUser;
import com.wteam.framework.common.security.context.UserContext;
import com.wteam.framework.common.vo.ResultMessage;
import com.wteam.framework.modules.book.entity.Card;
import com.wteam.framework.modules.book.entity.OrderInfo;
import com.wteam.framework.modules.book.entity.PaymentInfo;
import com.wteam.framework.modules.book.entity.Venue;
import com.wteam.framework.modules.book.mapper.CardMapper;
import com.wteam.framework.modules.book.mapper.OrderInfoMapper;
import com.wteam.framework.modules.book.mapper.PaymentInfoMapper;
import com.wteam.framework.modules.book.mapper.VenueMapper;
import com.wteam.framework.modules.book.service.CardService;
import com.wteam.framework.modules.book.service.OrderInfoService;
import com.wteam.framework.modules.book.service.PaymentInfoService;
import com.wteam.framework.modules.system.entity.dto.WechatPaymentSetting;
import com.wteam.framework.modules.system.service.SettingService;
import com.wteam.framework.modules.user.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotNull;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;

import static com.wteam.framework.modules.book.service.impl.OrderInfoServiceImpl.getWechatPaymentSetting;

/**
 * (PaymentInfo)表服务实现类
 *
 * @author doncic
 * @since 2023-09-20 19:20:06
 */
@Slf4j
@Service("paymentInfoService")
public class PaymentInfoServiceImpl extends ServiceImpl<PaymentInfoMapper, PaymentInfo> implements PaymentInfoService {


    @Autowired
    private UserMapper userMapper;
    @Autowired
    private OrderInfoService orderInfoService;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private SettingService settingService;
    @Autowired
    private VenueMapper venueMapper;
    @Autowired
    private PaymentInfoService paymentInfoService;
    @Autowired
    private CardMapper cardMapper;
    @Autowired
    private CardService cardService;
//    @Autowired
//    private RedisTemplate<String, OrderInfo> redisTemplate;

    /**
     * 调用jeepay统一下单接口
     *
     * @param id
     * @return
     * @throws JeepayException
     */

    @Override
    public void wxpay(@NotNull Long id) {
        //根据传入的订单id查询支付金额
        OrderInfo orderInfo = orderInfoMapper.selectById(id);
        if (orderInfo == null) {
            throw new ServiceException("对应订单不存在");
        }
        //获取到对应场地信息
        Long venueId = orderInfo.getVenueId();
        log.info("此时场地的id为：{}", venueId);
        Venue venue = venueMapper.selectById(venueId);
        if (venue == null) {
            throw new ServiceException("对应场地信息不存在");
        }
        Long orderPrice = orderInfo.getOrderPrice().longValue();
        log.info("该订单支付金额为：{}", orderPrice);
        // 调用 getWechatPaymentSetting 方法获取微信支付配置信息
        WechatPaymentSetting wechatPaymentSetting = getWechatPaymentSetting(settingService);
        log.info("微信支付配置信息为:{}", wechatPaymentSetting);
        JeepayClient jeepayClient = JeepayClient.getInstance(wechatPaymentSetting.getAppId(), wechatPaymentSetting.getApiKey3());
        String wayCode = "WX_LITE";                           // 支付方式
        PayOrderCreateRequest request = new PayOrderCreateRequest();
        PayOrderCreateReqModel model = new PayOrderCreateReqModel();
        model.setMchNo(wechatPaymentSetting.getMchId());                       // 商户号
        model.setAppId(jeepayClient.getAppId());            // 应用ID
        String orderNo = "mho" + new Date().getTime();
        model.setMchOrderNo(orderNo);                       // 商户订单号
        model.setWayCode(wayCode);                          // 支付方式
        model.setAmount(orderPrice);                                // 金额，单位分
        model.setCurrency("CNY");                           // 币种，目前只支持cny
        model.setClientIp("1.14.25.22");                 // 发起支付请求客户端的IP地址
        model.setSubject("商品标题");                         // 商品标题
        model.setBody("商品描述");                            // 商品描述
        model.setNotifyUrl("https://www.jeequan.com");      // 异步通知地址
        model.setReturnUrl("");                             // 前端跳转地址
        model.setChannelExtra("");       // 渠道扩展参数
        model.setExtParam("");                              // 商户扩展参数,回调时原样返回
        log.info("此时的model参数为：{}", model);
        request.setBizModel(model);
        try {
            PayOrderCreateResponse response = jeepayClient.execute(request);
            log.info("验签结果：{}", response.checkSign(Jeepay.apiKey));
            // 下单成功
            if (response.isSuccess(Jeepay.apiKey)) {
                String payOrderId = response.get().getPayOrderId();
                log.info("payOrderId：{}", payOrderId);
                log.info("mchOrderNo：{}", response.get().getMchOrderNo());
            } else {
                log.info("下单失败：{}", orderNo);
                log.info("通道错误码：{}", response.get().getErrCode());
                log.info("通道错误信息：{}", response.get().getErrMsg());
            }
        } catch (JeepayException e) {
            log.error(e.getMessage());
        }
    }


    @Override
    public ResultMessage refund(@NotNull Long id) {
        JeepayClient jeepayClient = JeepayClient.getInstance(Jeepay.appId, Jeepay.apiKey, Jeepay.getApiBase());
        RefundOrderCreateRequest request = new RefundOrderCreateRequest();
        RefundOrderCreateReqModel model = new RefundOrderCreateReqModel();
        model.setMchNo(getWechatPaymentSetting(settingService).getMchId());                       // 商户号
        model.setAppId(jeepayClient.getAppId());            // 应用ID
        model.setMchOrderNo("");                            // 商户支付单号(与支付订单号二者传一)
        model.setPayOrderId("P202106181104177050002");      // 支付订单号(与商户支付单号二者传一)
        String refundOrderNo = "mho" + new Date().getTime();
        model.setMchRefundNo(refundOrderNo);                // 商户退款单号
        model.setRefundAmount(4l);                          // 退款金额，单位分
        model.setCurrency("cny");                           // 币种，目前只支持cny
        model.setClientIp("192.166.1.132");                 // 发起支付请求客户端的IP地址
        model.setRefundReason("退款测试");                    // 退款原因
        model.setNotifyUrl("https://www.jeequan.com");      // 异步通知地址
        model.setChannelExtra("");                          // 渠道扩展参数
        model.setExtParam("");                              // 商户扩展参数,回调时原样返回
        request.setBizModel(model);
        try {
            RefundOrderCreateResponse response = jeepayClient.execute(request);
            log.info("验签结果：{}", response.checkSign(Jeepay.apiKey));
            // 判断退款发起是否成功（并不代表退款成功）
            if (response.isSuccess(Jeepay.apiKey)) {
                String refundOrderId = response.get().getRefundOrderId();
                log.info("refundOrderId：{}", refundOrderId);
                log.info("mchRefundNo：{}", response.get().getMchRefundNo());
            } else {
                log.info("下单失败：refundOrderNo={}, msg={}", refundOrderNo, response.getMsg());
                log.info("通道错误码：{}", response.get().getErrCode());
                log.info("通道错误信息：{}", response.get().getErrMsg());
            }
        } catch (JeepayException e) {
            log.error(e.getMessage());
        }
        return ResultUtil.success();
    }

    @Override
    public ResultMessage cardPay(String accessToken, @NotNull Long cardId, @NotNull Long orderId) {
        // 根据传入的token获取用户信息
        AuthUser authUser = UserContext.getAuthUser(accessToken);
        if (authUser == null) {
            return ResultUtil.error(ResultCode.USER_NOT_FOUND);
        }
        // 获得用户id
        Long userId = Long.valueOf(authUser.getId());
        Card card = cardMapper.selectById(cardId);
        //获取折扣值
        Float discountValue = card.getDiscountValue();
        //获得金额
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        if (ObjectUtil.isNull(orderInfo)) {
            throw new ServiceException("此时订单信息为空");
        }
        if (ObjectUtil.isNull(card)) {
            throw new ServiceException("此时卡信息为空");
        }
        if (!userId.equals(card.getUserId())) {
            return ResultUtil.error(ResultCode.UNAUTHORIZED); // 非法操作，不是卡的所有者
        }
        // 检查余额是否足够支付订单
        Double currentBalance = Double.valueOf(card.getCurrentBalance());
        // 获取支付金额
        Double orderPrice = orderInfo.getOrderPrice();
        double v = orderPrice * discountValue;
        if (v < currentBalance) {
            throw new ServiceException("余额不足！");
        }
        //计算扣除值
        card.setCurrentBalance((currentBalance - v));
        boolean save = cardService.save(card);
        if (save) {
            return ResultUtil.success();
        }
        return ResultUtil.error(ResultCode.CARD_PAY_ERROR);
    }

    /**
     * md5签名生成算法
     *
     * @param input
     * @return
     */
    public String generateMD5Signature(String input) {
        try {
            // 创建MessageDigest对象，指定算法为MD5
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 将输入字符串转换为字节数组
            byte[] inputBytes = input.getBytes(StandardCharsets.UTF_8);
            // 计算MD5摘要
            byte[] hashBytes = md.digest(inputBytes);
            // 将摘要转换为十六进制字符串
            StringBuilder result = new StringBuilder();
            for (byte hashByte : hashBytes) {
                // 将每个字节转换为两位的十六进制表示
                result.append(String.format("%02x", hashByte));
            }
            return result.toString();
        } catch (NoSuchAlgorithmException e) {
            // 处理异常
            e.printStackTrace();
            return null;
        }
    }

    private PaymentInfo paymentInfo(String payOrderId) {
        PaymentInfo paymentInfo = new PaymentInfo();
        paymentInfo.setId(payOrderId);
        return paymentInfo;
    }

}
