package com.miaxis.app.controller.wx;


import com.alibaba.fastjson.JSONObject;
import com.miaxis.common.config.WxpayConfig;
import com.miaxis.common.constant.Constants;
import com.miaxis.common.exception.CustomException;
import com.miaxis.common.utils.AesUtil;
import com.miaxis.newgzpt.service.IGzptUserInfoService;
import com.miaxis.newgzpt.service.IGzptVideoVipService;
import com.miaxis.order.service.IOrderInfoService;
import com.miaxis.userInfo.service.IUserVipService;
import com.miaxis.wx.domain.RefundRecord;
import com.miaxis.wx.domain.WxJsOrder;
import com.miaxis.wx.dto.WxNotifyReturnDTO;
import com.miaxis.wx.dto.WxpayNotifyDTO;
import com.miaxis.wx.service.IRefundRecordService;
import com.miaxis.wx.service.IWxJsOrderService;
import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.X509Certificate;

@RestController
@RequiredArgsConstructor
@RequestMapping(Constants.OPEN_PREFIX + "/wx/notify")
@Api(tags = {"【APP-微信回调】"})
@Slf4j
public class WxNotifyController {

    @Autowired
    private WxpayConfig wxpayConfig;

    @Autowired
    private IWxJsOrderService wxJsOrderService;

    @Autowired
    private IRefundRecordService refundRecordService;

    @Autowired
    private AutoUpdateCertificatesVerifier verifier;

    @Autowired
    private IGzptUserInfoService userInfoService;


    @Autowired
    private IGzptVideoVipService videoVipService;

    @Autowired
    private IOrderInfoService orderInfoService;

    @Autowired
    private IUserVipService userVipService;

    /**
     * 微信支付回调接口
     */
    @PostMapping(value = "/wxpay")
    @ApiOperation("微信支付回调")
    public WxNotifyReturnDTO wxpayNotify(@RequestBody WxpayNotifyDTO wxpayNotifyDTO, HttpServletRequest request) throws GeneralSecurityException, IOException {
        String bodyString = getBodyString(request);
        if (!validate(request, bodyString)) {
           throw new CustomException("签名失败");
        }
        String resourceString = getSourString(wxpayNotifyDTO);
        log.info(resourceString);
        JSONObject jsonObject = JSONObject.parseObject(resourceString);
        //将回调数据写入数据库
        writeNotifyDataToDb(jsonObject);

        WxNotifyReturnDTO wxNotifyReturnDTO = new WxNotifyReturnDTO();
        wxNotifyReturnDTO.setCode("SUCCESS");
        wxNotifyReturnDTO.setMessage("成功");
        return wxNotifyReturnDTO;
    }


    @Transactional
    public void writeNotifyDataToDb(JSONObject jsonObject) {
        System.out.println(jsonObject);
        String outTradeNo = jsonObject.getString("out_trade_no");
        WxJsOrder wxJsOrder = wxJsOrderService.getByOutTradeNo(outTradeNo);
        if (wxJsOrder == null) {
            log.error("该订单不存在");
            return;
        }
        if ("SUCCESS".equals(wxJsOrder.getTradeState())) {
            log.info("订单号为" + wxJsOrder.getOutTradeNo() + "的订单已完成操作，无法重复操作！");
            return;
        }
        wxJsOrder.setTransactionId(jsonObject.getString("transaction_id"));
        JSONObject amount = jsonObject.getJSONObject("amount");
        wxJsOrder.setPayerTotal(amount.getInteger("payer_total"));
        wxJsOrder.setTotal(amount.getInteger("total"));
        wxJsOrder.setCurrency(amount.getString("currency"));
        wxJsOrder.setPayerCurrency(amount.getString("payer_currency"));
        wxJsOrder.setTradeState(jsonObject.getString("trade_state"));
        wxJsOrder.setBankType(jsonObject.getString("bank_type"));
        DateTime dateTime = new DateTime(jsonObject.getString("success_time"));
        wxJsOrder.setSuccessTime(dateTime.toDate());
        wxJsOrder.setTradeStateDesc(jsonObject.getString("trade_state_desc"));
        wxJsOrder.setTradeType(jsonObject.getString("trade_type"));
        wxJsOrder.setAttach(jsonObject.getString("attach"));
        wxJsOrder.setOrderStatus("2");

        //插入VIP信息
        //writeVipDataToDb(wxJsOrder);
//        orderInfoService.writeVipDataToDb(wxJsOrder.getGoodsName(),wxJsOrder.getUserId(),wxJsOrder.getUserName(),wxJsOrder.getOutTradeNo(),wxJsOrder.getTotal(),1,
//                wxJsOrder.getDqbh(),wxJsOrder.getDqmc(), wxJsOrder.getIsShare(),wxJsOrder.getSchool(),wxJsOrder.getSchoolName(),wxJsOrder.getSchoolCommission(),wxJsOrder.getPhoneType());

        //
        if(wxJsOrder.getGoodsType()==null || wxJsOrder.getGoodsType()==1) { //VIP套餐
            orderInfoService.writeVipDataToDb(wxJsOrder,1);
        }else if(wxJsOrder.getGoodsType()==2) { //考场
            orderInfoService.writeExamDataToDb(wxJsOrder,1);
        }
        wxJsOrderService.updateById(wxJsOrder);

    }

    private String getBodyString(HttpServletRequest request) {
        BufferedReader br = null;
        StringBuilder sb = new StringBuilder("");
        try {
            br = request.getReader();
            String str;
            while ((str = br.readLine()) != null) {
                sb.append(str);
            }
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();

    }

    private Boolean validate(HttpServletRequest request, String bodyString) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
        String sign = request.getHeader("Wechatpay-Signature");
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        String nonce = request.getHeader("Wechatpay-Nonce");

        StringBuffer sb = new StringBuffer();
        sb.append(timestamp + "\n");
        sb.append(nonce + "\n");
        sb.append(bodyString + "\n");
        X509Certificate validCertificate = verifier.getValidCertificate();
        // 进行签名服务
        Signature signature = Signature.getInstance("SHA256withRSA");
        // 用微信平台公钥对签名器进行初始化
        signature.initVerify(validCertificate);
        // 把我们构造的验签名串更新到签名器中
        signature.update(sb.toString().getBytes(StandardCharsets.UTF_8));
        Boolean result = signature.verify(Base64Utils.decodeFromString(sign));
        log.info("微信支付回调验签:" + result.toString());
        return result;

    }


    /**
     * 微信退款回调
     */
    @PostMapping(value = "/refund")
    @ApiOperation("微信退款回调")
    public WxNotifyReturnDTO refundNotify(@RequestBody WxpayNotifyDTO wxpayNotifyDTO, HttpServletRequest request) throws GeneralSecurityException, IOException {
        String bodyString = getBodyString(request);
        if (!validate(request, bodyString)) {
            throw new CustomException("签名失败");
        }
        String resourceString = getSourString(wxpayNotifyDTO);
        log.info(resourceString);
        JSONObject jsonObject = JSONObject.parseObject(resourceString);
        //将回调数据写入数据库
        writeRefundNotifyDataToDb(jsonObject);

        WxNotifyReturnDTO wxNotifyReturnDTO = new WxNotifyReturnDTO();
        wxNotifyReturnDTO.setCode("SUCCESS");
        wxNotifyReturnDTO.setMessage("成功");
        return wxNotifyReturnDTO;
    }





    /**
     * 新退款方便
     * @param jsonObject
     */
    private void writeRefundNotifyDataToDb(JSONObject jsonObject) {
        String refundId = jsonObject.getString("refund_id");
        String outTradeNo = jsonObject.getString("out_trade_no");
        RefundRecord refundRecord = refundRecordService.getByRefundId(refundId);
        if (refundRecord == null) {
            log.error("该退款订单不存在");
            return;
        }
        refundRecord.setTransactionId(jsonObject.getString("transaction_id"));
        refundRecord.setUserReceivedAccount(jsonObject.getString("user_received_account"));
        refundRecord.setStatus(jsonObject.getString("refund_status"));
        refundRecordService.updateById(refundRecord);

        if ("SUCCESS".equals(refundRecord.getStatus())) {
            //退款成功

        }
    }





    private String getSourString(WxpayNotifyDTO wxpayNotifyDTO) throws GeneralSecurityException, IOException {
        AesUtil aesUtil = new AesUtil(wxpayConfig.getV3key().getBytes());
        WxpayNotifyDTO.WxpaySource wxpaySource = wxpayNotifyDTO.getResource();
        return aesUtil.decryptToString(wxpaySource.getAssociated_data().getBytes(), wxpaySource.getNonce().getBytes(), wxpaySource.getCiphertext());
    }


    @Data
    public class FilmNotifyReturnDTO {
        String code;
        String message;
        Boolean success;
    }


    public static void main(String[] args) {

        String s = "35,45,31,19.5";
        String[] values= s.split(",");
        int priceApple = Integer.parseInt(values[3]) *100;   //订单总额
        System.out.println(priceApple);

    }
}
