package com.ruoyi.hezhi.api.kaoshi;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.alipay.api.internal.util.AlipaySignature;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.weixin.config.WeiXinPayConfig;
import com.ruoyi.common.weixin.utils.WeiXinPayV3Utils;
import com.ruoyi.hezhi.api.entity.AliPayConfig;
import com.ruoyi.hezhi.api.entity.AlipayService;
import com.ruoyi.hezhi.domain.TbExamRegistration;
import com.ruoyi.hezhi.domain.TbMemberOrder;
import com.ruoyi.hezhi.domain.dto.ExamPayInfoDto;
import com.ruoyi.hezhi.service.ITbExamRegistrationService;
import com.ruoyi.hezhi.service.ITbMemberOrderService;
import com.ruoyi.hezhi.service.IWxPayService;
import io.swagger.annotations.Api;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 支付
 */
@Api("支付")
@RestController
@RequestMapping("/api/pay")
public class ApiPayController {

    private static final Logger log = LoggerFactory.getLogger(ApiPayController.class);
    @Resource
    private ITbMemberOrderService memberOrderService;

    @Resource
    private WeiXinPayV3Utils weiXinPayV3Utils;

    @Resource
    private AliPayConfig aliPayConfig;
    @Resource
    private AlipayService alipayService;
    @Resource
    private WeiXinPayConfig weiXinPayConfig;
    @Resource
    private IWxPayService wxPayService;
    @Resource
    private ITbExamRegistrationService examRegistrationService;

    /**
     * alipay扫码支付
     */
    @GetMapping("/aliPayScanCode")
    public AjaxResult aliPayScanCode(String orderNo) {
        //todo 检测考试报名时间是否过了（支付宝）【待测试】
        if (StrUtil.isBlank(orderNo)) {
            return AjaxResult.error("参数错误");
        }
        ExamPayInfoDto examPayInfoDto = memberOrderService.selectExamPayInfoByOrderNo(orderNo);
        if(examPayInfoDto!=null&&examPayInfoDto.getIsExpired()==1){
            return AjaxResult.error("考试报名时间已过，请重新报名");
        }
        TbMemberOrder order = memberOrderService.selectOrderByOrderNo(orderNo);
        if (ObjectUtils.isEmpty(order)) {
            return AjaxResult.error("参数错误");
        }
        JSONObject result = new JSONObject();

        BigDecimal payPrice = order.getPayPrice();

        if (payPrice.compareTo(BigDecimal.ZERO) < 1){
            // 无需支付
            result.put("isNeedPay", 0);
            memberOrderService.orderPayNotify(order.getOrderNo(), 2);
        }else {
            // 需要支付
            result.put("isNeedPay", 1);
            log.info("支付宝预下单，商户订单号：{}", orderNo);
            try {
                TbExamRegistration tbExamRegistration = examRegistrationService.selectTbExamRegistrationByExamRegistrationIdFahuo(order.getDataId());
                if (ObjectUtil.isNull(tbExamRegistration)) {
                    return AjaxResult.error("获取报名信息失败，下单失败");
                }
                String payInfo = alipayService.aliPaySubmit(order.getPayPrice(), order.getOrderNo(), order.getOrderName(),tbExamRegistration.getExamId(),tbExamRegistration.getMemberUserId());
                result.put("payInfo", payInfo);
            } catch (Exception e) {
                e.printStackTrace();
                return AjaxResult.error("下单失败");
            }
        }
        return AjaxResult.success(result);
    }

    /***
     * 获取微信支付二维码
     * @param orderNo 订单号
     * @return 结果
     */
    @GetMapping("/createNativePayParam")
    public AjaxResult createNativePayParam(String orderNo) {
        //todo 检测考试报名时间是否过了（微信）【待测试】
        if (StrUtil.isBlank(orderNo)) {
            throw new ServiceException("参数错误");
        }
        ExamPayInfoDto examPayInfoDto = memberOrderService.selectExamPayInfoByOrderNo(orderNo);
        if(examPayInfoDto!=null&&examPayInfoDto.getIsExpired()==1){
            return AjaxResult.error("考试报名时间已过，请重新报名");
        }
        TbMemberOrder order = memberOrderService.selectOrderByOrderNo(orderNo);
        if (ObjectUtils.isEmpty(order)) {
            throw new ServiceException("订单错误");
        }

        BigDecimal payPrice = order.getPayPrice();

        if(payPrice.compareTo(BigDecimal.ZERO) < 1) {
            // 无需支付
            JSONObject data = new JSONObject();
            data.put("isNeedPay", 0);
            memberOrderService.orderPayNotify(orderNo, 1);
            return AjaxResult.success(data);
        }else {
            JSONObject amount = new JSONObject();
            //单位为人民币（分）
            amount.put("total", order.getPayPrice().multiply(new BigDecimal("100")).intValue());
            amount.put("currency", "CNY");

            JSONObject postData = new JSONObject();
            postData.put("appid", weiXinPayConfig.getAppId());
            postData.put("mchid", weiXinPayConfig.getMchId());
            postData.put("description", order.getRemarks());
            postData.put("out_trade_no", orderNo);
            postData.put("notify_url", weiXinPayConfig.getNotifyUrl());
            postData.put("amount", amount);

            log.info("NATIVE下单-参数 => {}", postData.toJSONString());

            // 发送请求
            JSONObject result = weiXinPayV3Utils.sendPost("https://api.mch.weixin.qq.com/v3/pay/transactions/native", postData);
            log.info("NATIVE下单-结果 => {}", postData.toJSONString());
            if (result.containsKey("code_url")) {
                // 支付二维码
                HashMap<String, Object> map = new HashMap<>();
                map.put("codeUrl", result.getString("code_url"));
                map.put("isNeedPay", 1);
                return AjaxResult.success(map);
            } else {
                log.error("NATIVE下单调起失败 <{}> 参数：{}，结果：{}", DateUtils.getTime(), postData.toJSONString(), result.toJSONString());
                throw new ServiceException("NATIVE下单调起失败");
            }
        }
    }

    /**
     * 微信支付二维码支付回调
     *
     * @param httpServletRequest  请求
     * @param httpServletResponse 响应
     */
    @ResponseBody
    @PostMapping("/createNativePayParamNotify")
    public String createNativePayParamNotify(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
        log.info("微信支付二维码支付回调 ->" + httpServletRequest);
        String code = "FAIL";
        String message = "";
        try {
            /// 解析回调参数
            JSONObject callbackData = weiXinPayV3Utils.getNotifyDate(httpServletRequest);
            if (ObjectUtil.isNotEmpty(callbackData)) {
                log.info("支付回调参数 ->" + callbackData.toJSONString());
                if (callbackData.containsKey("trade_state") && "SUCCESS".equals(callbackData.get("trade_state"))) {
                    // 支付成功
                    String orderNo = callbackData.getString("out_trade_no");

                    String msg = "";
                    try {
                        msg = memberOrderService.orderPayNotify(orderNo, 1);
                    } catch (Exception e) {
                        e.printStackTrace();
                        msg = "FAIL";
                    }

                    if ("SUCCESS".equals(msg)) {
                        code = "SUCCESS";
                    } else {
                        message = "商户业务处理异常";
                    }

                } else {
                    message = "回调参数异常";
                }
            } else {
                message = "回调参数解析异常";
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("微信支付回调，解析异常");
            message = "回调参数解析异常";
        }
        // 响应报文
        JSONObject returnJson = new JSONObject();
        returnJson.put("code", code);
        returnJson.put("message", message);
        return returnJson.toJSONString();
    }

    /**
     * 支付宝支付回调-学信考试支付
     * @param httpServletRequest 请求
     * @param httpServletResponse 响应
     */
    @PostMapping("/aliPayBoilerNotify")
    @ResponseBody
    public String aliPayBoilerNotify(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse){
        try {
            //获取支付宝POST过来反馈信息
            //获取支付宝POST过来反馈信息，将异步通知中收到的待验证所有参数都存放到map中
            Map< String , String > params = new HashMap< String , String >();
            Map requestParams = httpServletRequest.getParameterMap();
            for(Iterator iter = requestParams.keySet().iterator(); iter.hasNext();){
                String name = (String)iter.next();
                String[] values = (String [])requestParams.get(name);
                String valueStr = "";
                for(int i = 0;i < values.length;i ++ ){
                    valueStr =  (i==values.length-1)?valueStr + values [i]:valueStr + values[i] + ",";
                }
                //乱码解决，这段代码在出现乱码时使用。
                //valueStr = new String(valueStr.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
                params.put (name,valueStr);
            }
            log.error("支付宝支付回调-学信考试支付 <{}> 订单参数 <{}> ", DateUtils.getTime(), params);
            boolean flag = AlipaySignature.rsaCheckV1 (params, aliPayConfig.getPublicKey(), "UTF-8","RSA2");
            if (flag){
                // 对支付结果中的业务进行验证
                String s = alipayService.checkParams(params);
                if (s.equals("success")){
                    log.error("支付宝支付回调-学信考试支付 <{}> 签名认证成功 <{}> ", DateUtils.getTime(), params);
                    String orderNo = params.get("out_trade_no");
                    // 业务处理
                    String msg = "";
                    try {
                        msg = memberOrderService.orderPayNotify(orderNo, 2);
                    }catch (Exception e){
                        log.error("支付宝支付回调-学信考试支付<{}> 订单号 <{}> 订单处理异常", DateUtils.getTime(), orderNo);
                        msg = "FAIL";
                    }
                    if(msg.equals("SUCCESS")){
                        return "success";
                    }else{
                        return "fail";
                    }
                }else{
                    log.error("支付宝支付回调-学信考试支付 <{}> 签名认证失败 <{}> ", DateUtils.getTime(), params);
                    return "fail";
                }
            }else{
                log.error("支付宝支付回调-学信考试支付 <{}> 解密失败 <{}> ", DateUtils.getTime(), params);
                return "fail";
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "fail";
        }
    }

    /**
     * 查询订单状态
     *
     * @param orderNo 订单编号
     * @return ok
     */
    @GetMapping("/getOrderStatus")
    public AjaxResult getOrderStatus(String orderNo) {
        try {
            return AjaxResult.success().put("data", memberOrderService.selectOrderByOrderNo(orderNo));
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("查询订单状态异常");
        }
    }

    @GetMapping("/test")
    public AjaxResult test(){

        String s = memberOrderService.orderPayNotify("1870522601479000064", 1);
        return AjaxResult.success();
    }

    /**
     * 创建订单支付
     */
    @GetMapping("/createWxOrder")
    public AjaxResult createWxOrder(@RequestParam String orderNo) {
        return AjaxResult.success(wxPayService.createOrder(orderNo));
    }

}
