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.UserInfo;
import com.miaxis.common.core.page.ResponsePageInfo;
import com.miaxis.common.exception.CustomException;
import com.miaxis.common.utils.SecurityUtils;
import com.miaxis.common.utils.uuid.CommonUtils;
import com.miaxis.wx.domain.WxOrder;
import com.miaxis.wx.dto.*;
import com.miaxis.wx.service.IWxOrderService;
import com.miaxis.system.service.ISysDictDataService;
import io.swagger.annotations.*;
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.*;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.security.PrivateKey;
import java.security.Signature;
import java.util.Base64;
import java.util.List;

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

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

    @Autowired
    private HttpClient httpClient;

    @Autowired
    private WxpayConfig wxpayConfig;

    @Autowired
    private IWxOrderService wxOrderService;


    @Autowired
    private ISysDictDataService dictDataService;

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






    @GetMapping("/order/list")
    @ApiOperation("查询订单列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum",value = "当前页码" ,dataType = "int", paramType = "query", required = false),
            @ApiImplicitParam(name = "pageSize",value = "每页数据量" , dataType = "int", paramType = "query", required = false),
    })
    public ResponsePageInfo<WxOrder> list(@ModelAttribute WxOrderListDTO wxOrderListDTO){

        String openid = SecurityUtils.getLoginUser().getStudent().getOpenid();
        startPage();
        wxOrderListDTO.setOpenid(openid);
        List<WxOrder> list = wxOrderService.selectOrderList(wxOrderListDTO);
        return toResponsePageInfo(list);
    }

    /**
     * 微信支付获取预订单id
     */
    @PostMapping(value = "/prepareOrderForFulu")
    @ApiOperation("微信支付福禄下单")
    public Response<JSONObject> getPrepareOrderIdForFulu(@RequestBody WxOrderCreateFuluDTO wxOrderCreateFuluDTO) throws Exception{

        //创建本地微信订单
        WxOrder order = new WxOrder();
        UserInfo student = SecurityUtils.getLoginUser().getStudent();
        String orderCode = getOrderCode(student.getId());
        order.setOutTradeNo(orderCode);
        order.setOpenid(student.getOpenid());
        order.setGoodsType("2");
        //保存电影下单数据
        wxOrderService.createFuluOrder(order,wxOrderCreateFuluDTO);
        wxOrderService.save(order);
        return Response.success(placeWxOrder(order, "视频会员"));


    }

    /**
     * 微信支付获取预订单id
     */
    @PostMapping(value = "/prepareOrder")
    @ApiOperation("微信支付电影下单")
    public Response<JSONObject> getPrepareOrderId(@RequestBody WxOrderCreateDTO wxOrderCreateDTO) throws Exception{
        UserInfo student = SecurityUtils.getLoginUser().getStudent();
        //创建本地微信订单
        WxOrder order = new WxOrder();
        String orderCode = getOrderCode(student.getId());
        order.setOutTradeNo(orderCode);
        order.setOpenid(student.getOpenid());
        order.setGoodsType("1");
        order.setGoodsPictureUrl(wxOrderCreateDTO.getGoodsPictureUrl());
        //保存电影下单数据
        wxOrderService.createFilmOrder(order,wxOrderCreateDTO);
        wxOrderService.save(order);
        // 2 调用微信接口生成预订单,并返回调起支付所需json数据
        return Response.success(placeWxOrder(order, "电影票"));

    }

    //微信预订单
    private JSONObject placeWxOrder(WxOrder 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());
        rootNode.putObject("payer")
                .put("openid", order.getOpenid());
        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 JSONObject getWxParamJson(String bodyAsString, String orderCode) throws Exception {
        String  packageStr = "prepay_id="+JSONObject.parseObject(bodyAsString).get("prepay_id");
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("package",packageStr);
        String nonce_str = RandomStringUtils.randomAlphanumeric(32);
        jsonObject.put("nonceStr",nonce_str);
        long timestamp =  System.currentTimeMillis()/1000;
        jsonObject.put("timeStamp",String.valueOf(timestamp));
        jsonObject.put("signType","RSA");
        StringBuffer sb = new StringBuffer();
        sb.append(appid + "\n");
        sb.append(timestamp + "\n");
        sb.append(nonce_str + "\n");
        sb.append(packageStr+ "\n");
        System.out.println(sb);

        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);
        jsonObject.put("paySign",base64Str);
        jsonObject.put("outTradeNo",orderCode);
        return jsonObject;
    }

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

    /**
     * 获取微信订单详细信息
     */
    @GetMapping(value = "/{outTradeNo}")
    @ApiOperation("获取微信订单详细信息")
    public Response<WxOrder> getInfo(
            @ApiParam(name = "outTradeNo", value = "商家订单号", required = true)
            @PathVariable("outTradeNo") String outTradeNo
    ){
        WxOrder wxOrder = wxOrderService.getByOutTradeNo(outTradeNo);
        if (!wxOrder.getOpenid().equals(SecurityUtils.getLoginUser().getStudent().getOpenid())){
            throw new CustomException("该用户无访问此订单权限");
        }
        return Response.success(wxOrder);
    }








}
