package com.miaxis.app.controller.wx;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.miaxis.common.config.WxpayConfig;
import com.miaxis.common.constant.Constants;
import com.miaxis.common.core.controller.BaseController;
import com.miaxis.common.core.domain.Response;
import com.miaxis.common.core.domain.entity.SysDictData;
import com.miaxis.common.enums.OrderStatusEnum;
import com.miaxis.common.exception.CustomException;
import com.miaxis.common.utils.uuid.CommonUtils;
import com.miaxis.exam.domain.ExamInfo;
import com.miaxis.exam.service.IExamInfoService;
import com.miaxis.examvip.service.IVipUserExamService;
import com.miaxis.newgzpt.domain.GzptUserInfo;
import com.miaxis.newgzpt.service.IGzptSchActivationService;
import com.miaxis.newgzpt.service.IGzptSchPayConfigService;
import com.miaxis.newgzpt.service.IGzptUserInfoService;
import com.miaxis.system.service.ISysDictDataService;
import com.miaxis.wx.domain.WxJsOrder;
import com.miaxis.wx.dto.WxOrderDTO;
import com.miaxis.wx.dto.WxOrderGoodsDTO;
import com.miaxis.wx.service.IWxJsOrderService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
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 java.io.ByteArrayOutputStream;
import java.io.File;
import java.security.PrivateKey;
import java.security.Signature;
import java.util.Base64;

import static com.miaxis.common.utils.OrderCodeFactory.getOrderCode;

/**
 * 【小程序-微信支付】Controller
 *
 * @author miaxis
 * @date 2021-03-10
 */
@RestController
@RequiredArgsConstructor
@RequestMapping(Constants.OPEN_PREFIX+"/wxjs")
@Api(tags = {"【APP-微信支付】"})
@Slf4j
public class WxJsjpController extends BaseController {

    @Autowired
    private HttpClient httpClient;

    @Autowired
    private WxpayConfig wxpayConfig;

    @Autowired
    private IWxJsOrderService wxJsOrderService;

    @Autowired
    private ISysDictDataService dictDataService;

    @Value("${app.appid}")
    private String appid;
    @Value("${wxpay.notifyUrl}")
    private  String notifyUrl ;

    @Autowired
    private IGzptUserInfoService userInfoService;

    @Autowired
    private IGzptSchPayConfigService schPayConfigService;

    @Autowired
    private IGzptSchActivationService schActivationService;

    @Autowired
    private IVipUserExamService vipUserExamService;

    @Autowired
    private IExamInfoService examInfoService;


    /**
     * 微信支付获取预订单id
     */
    @PostMapping(value = "/prepareOrder")
    @ApiOperation("极速驾培微信下单")
    public Response<WxParamEntity> getPrepareOrder(@RequestBody WxOrderDTO wxOrderDTO) throws Exception{
        SysDictData sysDictData = dictDataService.selectDictDataById(wxOrderDTO.getDictCode());
        String[] values = sysDictData.getDictValue().split(",");

        int isShare = 0;

        //创建本地微信订单
        WxJsOrder order = new WxJsOrder();
        GzptUserInfo gzptUserInfo = userInfoService.getInfoById(wxOrderDTO.getUserId());
        //获取合作驾校配置表
        isShare = schPayConfigService.isSchPayConfigByUser(gzptUserInfo);

        String orderCode = getOrderCode(gzptUserInfo.getId());
        order.setOutTradeNo(orderCode);
        order.setUserId(gzptUserInfo.getId());
        order.setUserName(gzptUserInfo.getUserName());
        order.setLogincode(gzptUserInfo.getLogincode());
        order.setGoodsName(sysDictData.getDictLabel());
        order.setGoodsType(1);
        order.setPhoneType(wxOrderDTO.getPhoneType());  //手机类型
        order.setDqbh(gzptUserInfo.getCity());
        order.setDqmc(gzptUserInfo.getCityName());
        order.setSchool(gzptUserInfo.getSchool());
        order.setSchoolName(gzptUserInfo.getSchoolName());
        order.setIsShare(isShare);
        order.setCreateId(gzptUserInfo.getOutCreateId());

        Double price = Double.parseDouble(values[0])*100;   //订单总额
        int b =  new Double(price).intValue();
        order.setTotal(b);

        if(isShare==1) {
            //如果是合作驾校
            if (wxOrderDTO.getPhoneType()!=null && wxOrderDTO.getPhoneType()==1) { //苹果
                int priceApple = Integer.parseInt(values[3]);   //订单总额
                order.setSchoolCommission(priceApple);
            } else if (wxOrderDTO.getPhoneType()!=null && wxOrderDTO.getPhoneType()==2) { //安卓
                int priceAndroid = Integer.parseInt(values[2]);   //订单总额
                order.setSchoolCommission(priceAndroid);
            }
        }


       if(sysDictData.getDictLabel().indexOf("计时")!=-1){
           int isActiva = schActivationService.isSchActivation(gzptUserInfo.getOutId());
           if(isActiva==1){
               throw new CustomException("该学员已激活，请退出APP后再重新获取套餐");
           }
       }

        order.setOrderStatus(OrderStatusEnum.PROCESSING.getCode());
        wxJsOrderService.save(order);
        return Response.success(placeWxOrder(order, sysDictData.getDictLabel()));

    }

    /**
     * 微信支付获取预订单id
     */
    @PostMapping(value = "/getPrepareGoodsOrder")
    @ApiOperation("微信商品下单")
    public Response<WxParamEntity> getPrepareGoodsOrder(@RequestBody WxOrderGoodsDTO wxOrderGoodsDTO) throws Exception{
        if(wxOrderGoodsDTO.getGoodsType()==2) {
            GzptUserInfo gzptUserInfo = userInfoService.getInfoById(wxOrderGoodsDTO.getUserId());

            int count = vipUserExamService.getUserExamByUserIdAndGoodsId(wxOrderGoodsDTO.getUserId(), wxOrderGoodsDTO.getGoodsId());
            if (count > 0) {
                throw new CustomException("您已购买过该考场，退回上个页面，重新进入。");
            }
            ExamInfo examInfo = examInfoService.getById(wxOrderGoodsDTO.getGoodsId());
            //创建本地微信订单
            WxJsOrder order = new WxJsOrder();
            String orderCode = getOrderCode(wxOrderGoodsDTO.getUserId());
            order.setGoodsId(wxOrderGoodsDTO.getGoodsId());
            order.setGoodsName(examInfo.getName());
            order.setGoodsType(wxOrderGoodsDTO.getGoodsType());
            order.setOutTradeNo(orderCode);
            order.setUserId(wxOrderGoodsDTO.getUserId());
            order.setUserName(gzptUserInfo.getUserName());
            order.setLogincode(gzptUserInfo.getLogincode());
            order.setPhoneType(wxOrderGoodsDTO.getPhoneType()); //手机类型 1:苹果 2:安卓
            order.setTotal(examInfo.getPrice());
            order.setIsShare(0);
            order.setDqbh(gzptUserInfo.getCity());
            order.setDqmc(gzptUserInfo.getCityName());
            order.setSchool(gzptUserInfo.getSchool());
            order.setSchoolName(gzptUserInfo.getSchoolName());
            order.setCreateId(gzptUserInfo.getOutCreateId());
            order.setOrderStatus(OrderStatusEnum.PROCESSING.getCode());
            wxJsOrderService.save(order);
            return Response.success(placeWxOrder(order, examInfo.getName()));
        } else if (wxOrderGoodsDTO.getGoodsType()==3) {
            throw new CustomException("请正确传入GoodsType，GoodsType=2未开发");
        } else {
            throw new CustomException("请正确传入GoodsType。");
        }

    }


    //下单
    private WxParamEntity placeWxOrder(WxJsOrder order, String goodsName) throws Exception {
        HttpPost httpPost = initHttpPost();
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode rootNode = objectMapper.createObjectNode();
        rootNode.put("mchid",wxpayConfig.getMerchantId())
                .put("appid", appid)
                .put("description", goodsName)
                .put("notify_url", notifyUrl)
                .put("out_trade_no", order.getOutTradeNo());
        rootNode.putObject("amount").put("total", order.getTotal());
        objectMapper.writeValue(bos, rootNode);
        httpPost.setEntity(new StringEntity(rootNode.toString(), "utf-8"));
        HttpResponse response = httpClient.execute(httpPost);
        String bodyAsString = EntityUtils.toString(response.getEntity());
        if (JSONObject.parseObject(bodyAsString).get("prepay_id") == null){
            throw new CustomException(JSONObject.parseObject(bodyAsString).get("message").toString());
        }
        return getWxParamJson(bodyAsString,order.getOutTradeNo());

    }

    // 生成调用调起微信支付所需参数
    private WxParamEntity getWxParamJson(String bodyAsString, String orderCode) throws Exception {
        WxParamEntity wxParamEntity = new WxParamEntity();
        wxParamEntity.setAppId(appid);
        wxParamEntity.setPartnerId(wxpayConfig.getMerchantId());
        String  prepayId = JSONObject.parseObject(bodyAsString).getString("prepay_id");
        wxParamEntity.setPrepayId(prepayId);
        wxParamEntity.setPackageValue("Sign=WXPay");
        String nonce_str = RandomStringUtils.randomAlphanumeric(32);
        wxParamEntity.setNonceStr(nonce_str);
        String timestamp = String.valueOf(System.currentTimeMillis()/1000);
        wxParamEntity.setTimeStamp(timestamp);

        StringBuffer sb = new StringBuffer();
        sb.append(appid + "\n");
        sb.append(timestamp + "\n");
        sb.append(nonce_str + "\n");
        sb.append(prepayId+ "\n");


        File file = new ClassPathResource("wechatpay/apiclient_key.pem").getFile();
        String realPath =file.getAbsolutePath();
        PrivateKey privateKey = CommonUtils.getPrivateKey(realPath);
        // 进行签名服务
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(sb.toString().getBytes("UTF-8"));
        byte[] signedData = signature.sign();
        String base64Str =  Base64.getEncoder().encodeToString(signedData);
        wxParamEntity.setSign(base64Str);

        return wxParamEntity;
    }

    private HttpPost initHttpPost() {
        HttpPost httpPost = new HttpPost(wxpayConfig.getV3url());
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type","application/json; charset=utf-8");
        return httpPost;
    }

    @Data
    class  WxParamEntity{
        String appId;
        String partnerId;
        String prepayId;
        String packageValue;
        String nonceStr;
        String timeStamp;
        String sign;

    }










}
