package com.miaxis.app.controller.tt;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.miaxis.common.config.WxpayConfig;
import com.miaxis.common.constant.Constants;
import com.miaxis.common.core.domain.entity.UserInfo;
import com.miaxis.common.exception.CustomException;
import com.miaxis.common.utils.AesUtil;
import com.miaxis.tt.domain.TtOrder;
import com.miaxis.tt.dto.TtNotifyReturnDTO;
import com.miaxis.tt.dto.TtpayNotifyDTO;
import com.miaxis.tt.dto.TtpaySource;
import com.miaxis.tt.service.ITtOrderService;
import com.miaxis.user.service.IUserInfoService;
import com.miaxis.vip.domain.VipCode;
import com.miaxis.vip.service.IVipCodeService;
import com.miaxis.wx.domain.RefundRecord;
import com.miaxis.wx.domain.WxOrder;
import com.miaxis.wx.dto.WxNotifyReturnDTO;
import com.miaxis.wx.dto.WxpayNotifyDTO;
import com.miaxis.wx.service.IRefundRecordService;
import com.miaxis.wx.service.IWxOrderService;
import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
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;
import java.util.Date;
import java.util.Random;

@RestController
@RequiredArgsConstructor
@RequestMapping(Constants.OPEN_PREFIX+"/tt/notify")
@Api(tags = {"【小程序-微信回调】"})
@Slf4j
public class TtNotifyController {


    @Autowired
    private WxpayConfig wxpayConfig;


    @Autowired
    private IWxOrderService wxOrderService;

    @Autowired
    private ITtOrderService ttOrderService;

    @Autowired
    private IVipCodeService vipCodeService;


    @Autowired
    private IUserInfoService userInfoService;


    @Autowired
    private  IRefundRecordService  refundRecordService;

    @Autowired
    private AutoUpdateCertificatesVerifier verifier;


    /**
     * 微信支付回调接口
     */
    @PostMapping(value = "/ttpay")
    @ApiOperation("头条支付回调")
    public TtNotifyReturnDTO wxpayNotify(@RequestBody TtpayNotifyDTO ttpayNotifyDTO) {

        //将回调数据写入数据库
        TtpaySource msg = JSONObject.parseObject(ttpayNotifyDTO.getMsg(), TtpaySource.class);
        writeNotifyDataToDb(msg);
        //创建兑换码
        String code = createCode();
        //激活用户
        avtivityCode(msg.getCp_orderno(),code);

        TtNotifyReturnDTO ttNotifyReturnDTO = new TtNotifyReturnDTO();
        ttNotifyReturnDTO.setErr_no(0);
        ttNotifyReturnDTO.setErr_tips("success");
        return ttNotifyReturnDTO;
    }

    private void avtivityCode(String outTradeNo, String vipCode) {
        TtOrder order= ttOrderService.getOne(new QueryWrapper<TtOrder>().eq("cp_orderno",outTradeNo));
        if (order ==  null){
            throw new CustomException("该订单不存在");
        }
        UserInfo userInfo = userInfoService.getOne(new QueryWrapper<UserInfo>().eq("union_id", order.getUnionId()));
        QueryWrapper<VipCode> queryWrapper = new QueryWrapper<VipCode>();
        queryWrapper.eq("vip_code", vipCode);
        VipCode vipCodeEntity = vipCodeService.getOne(queryWrapper);
        if (vipCodeEntity == null){
            throw new CustomException("该激活码不存在");
        }
        if (vipCodeEntity.getStatus() == 1){
            throw new CustomException("该激活码已被激活");
        }
        if (vipCodeEntity.getStatus() == 2){
            throw new CustomException("该激活码已作废");
        }
        vipCodeEntity.setStatus(1);
        vipCodeEntity.setActivationUserId(userInfo.getId());
        vipCodeEntity.setActivationTime(new Date());
        vipCodeService.updateById(vipCodeEntity);
        userInfo.setIsVip(1);
        userInfoService.updateById(userInfo);




    }

    private String createCode() {
        VipCode vipCode = new VipCode();
        String rVipCode = null ;
        do {
            rVipCode  = randomVipcode();
        }while (isRepeat(rVipCode));
        vipCode.setVipCode(rVipCode);
        vipCodeService.save(vipCode);
        return rVipCode;
    }


    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;

    }









    public void writeNotifyDataToDb(TtpaySource msg) {
        TtOrder order= ttOrderService.getOne(new QueryWrapper<TtOrder>().eq("cp_orderno",msg.getCp_orderno()));
        if (order == null) {
            throw new CustomException("该订单不存在");
        }
        order.setPaymentOrderNo(msg.getPayment_order_no());
        order.setChannelNo(msg.getChannel_no());
        order.setWay(msg.getWay());
        order.setCpExtra(msg.getCp_extra());
        order.setItemId(msg.getItem_id());
        order.setSellerUid(msg.getSeller_uid());
        order.setStatus(msg.getStatus());
        order.setTotalAmount(msg.getTotal_amount());
        order.setPaidAt(new Date(msg.getPaid_at()));
        ttOrderService.updateById(order);

    }

    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());
    }

    private String randomVipcode() {
        String result = "";
        Random random = new Random();
        for(int i =0 ;i <11 ;i ++){
            result+=random.nextInt(10);
        }
        return  result;


    }
    private boolean isRepeat(String rVipCode) {
        QueryWrapper<VipCode> wrapper = new QueryWrapper<VipCode>();
        wrapper.eq("vip_code",rVipCode);
        VipCode one = vipCodeService.getOne(wrapper);
        return one!= null;

    }






}
