package com.kmall.api.api.wxGlobal;

import com.kmall.api.annotation.IgnoreAuth;
import com.kmall.api.annotation.LoginUser;
import com.kmall.common.constant.Dict;
import com.kmall.api.entity.*;
import com.kmall.api.service.*;
import com.kmall.api.service.wxGlobal.ApiWxGlobalPayService;
import com.kmall.api.util.ApiBaseAction;
import com.kmall.api.util.CommonUtil;
import com.kmall.common.utils.CharUtil;
import com.kmall.common.utils.Constant;
import com.kmall.common.utils.XmlUtil;
import com.kmall.common.utils.wechat.AESUtil;
import com.kmall.common.utils.wechat.WechatRefundApiResult;
import com.kmall.common.utils.wechat.WechatRefundNotifyResult;
import com.kmall.common.utils.wechat.WechatUtil;
import com.kmall.common.utils.wechat.wxglobal.AesGcmExampleUtil;
import com.kmall.common.utils.wechat.wxglobal.WechatGlobalUtil;
import com.kmall.common.utils.wechat.wxglobal.dto.*;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;


/**
 * 微信境外支付
 *
 * @author huangyq
 * @email
 * @date 2018-12-11 17:01
 */
@RestController
@RequestMapping("/api/global/pay")
public class ApiWxGlobalPayController extends ApiBaseAction {
    private Logger logger = Logger.getLogger(ApiWxGlobalPayController.class);
    @Autowired
    private ApiOrderService orderService;
    @Autowired
    private ApiOrderGoodsService orderGoodsService;
    @Autowired
    private ApiWxGlobalPayService apiWxGlobalPayService;
    @Autowired
    private ApiOrderProcessRecordService orderProcessRecordService;
    @Autowired
    private ApiOrderExceptionRecordService apiOrderExceptionRecordService;
    @Autowired
    private ApiStoreService apiStoreService;

    /**
     * 发起支付
     * @param loginUser
     * @param orderIds
     * @param isMergePay
     * @return
     */
    @GetMapping("pay_prepay")
    public Object payPrepay(@LoginUser UserVo loginUser, Long[] orderIds,String isMergePay) {
        logger.info("微信支付接口>>>>>>payPrepay start");
        List<Long> orderIdList = new ArrayList<>();
        String merchOrderSn = "";
        for(int i=0;i<orderIds.length;i++){
            orderIdList.add(orderIds[i]);
        }
        BigDecimal actual_price = Constant.ZERO;
        String storeName = "";
        List<OrderVo> orderVoList = orderService.queryObjectByIdList(orderIdList);
        List<OrderProcessRecordEntity> processRecordEntityList = new ArrayList<>();

        for (OrderVo orderInfo:orderVoList) {
            if (orderInfo.getOrder_status() == 101) {
                return toResponsObject(400, "订单号为"+orderInfo.getOrder_sn()+"的订单超时支付，已取消", "");
            }
            if (orderInfo.getPay_status() != 0 && orderInfo.getPay_status() != 1) {
                return toResponsObject(400, "订单号为"+orderInfo.getOrder_sn()+"的订单已支付，请不要重复操作", "");
            }
            OrderProcessRecordEntity processRecordEntity = orderProcessRecordService.queryObjectByOrderSn(orderInfo.getOrder_sn());
            if(processRecordEntity != null){
                OrderProcessRecordEntity entity = new OrderProcessRecordEntity();
                entity.setOrderSn(orderInfo.getOrder_sn());
                entity.setUserId(Integer.valueOf(loginUser.getId()+""));
                entity.setId(processRecordEntity.getId());
                entity.setPayStartTime(new Date());
                processRecordEntityList.add(entity);
            }
            merchOrderSn = orderInfo.getMerchOrderSn();
            //如此次是单笔支付，则判断下单时该商户订单是否是拆单订单，如果都满足，则更新商户订单号，生成新的预支付信息
            if(Dict.isMergePay.item_0.getItem().equalsIgnoreCase(isMergePay)) {
                if ("2".equalsIgnoreCase(orderInfo.getIsMergePay())) {//多笔订单单笔支付,则商户订单号，生成新的预支付信息
                    merchOrderSn = "EMATO" + CommonUtil.generateOrderNumber();
                    orderInfo.setMerchOrderSn(merchOrderSn);
                }
            }
            actual_price = actual_price.add(orderInfo.getActual_price());
            StoreVo storeVo = apiStoreService.queryObject(orderInfo.getStore_id());
            storeName = storeVo.getStoreName();
        }
        String nonceStr = CharUtil.getRandomString(32).toUpperCase();
        Map<Object, Object> resultObj = new HashMap();

        try {
            //订单的商品
//            List<OrderGoodsVo> orderGoods = orderGoodsService.queryListByIds(orderIdList);
            String body = "中网国际跨境商城-"+storeName;
            //统一下单
            WechatGlobalQueryApiResult queryApiResult = WechatGlobalUtil.unifiedOrder(merchOrderSn,nonceStr, body, actual_price, loginUser.getWeixin_openid());
            // 响应报文
            String code = queryApiResult.getCode();
            if(StringUtils.isEmpty(queryApiResult.getPrepay_id())) {
                if (!code.equalsIgnoreCase("OK")) {
                    String message = queryApiResult.getMessage();
                    addOrderExceptionRecord(orderVoList, Dict.exceptionStatus.item_00.getItem(), "支付失败 ," + message);//记录订单异常信息
                    return toResponsFail("支付失败 ," + message);
                }
            }else{
                apiWxGlobalPayService.payPrepay(resultObj, queryApiResult, nonceStr, orderVoList);
                orderProcessRecordService.updateBatch(processRecordEntityList);//更新订单流转信息
                return toResponsObject(0, "微信统一订单下单成功", resultObj);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return toResponsFail("下单失败,error=" + e.getMessage());
        }
        return toResponsFail("下单失败");
    }

//    /**
//     * 更新订单支付失败流转信息
//     * @param processRecordEntityList
//     * @param return_msg
//     */
//    public void updateFailProcessBatch(List<OrderProcessRecordEntity> processRecordEntityList,String return_msg){
//        for (OrderProcessRecordEntity orderProcessRecordEntity : processRecordEntityList) {
//            orderProcessRecordEntity.setIsPaymentSend(Dict.isSend.item_0.getItem());
//            orderProcessRecordEntity.setProcessContent(return_msg);
//        }
//        orderProcessRecordService.updateBatch(processRecordEntityList);
//    }

    /**
     * 记录订单异常信息
     * @param orderVoList
     * @param exceptionStatus
     * @param expContent
     */
    public void addOrderExceptionRecord(List<OrderVo> orderVoList,String exceptionStatus,String expContent){
        for (OrderVo orderInfo: orderVoList) {
            MallOrderExceptionRecord mallOrderExceptionRecord = new MallOrderExceptionRecord();
            mallOrderExceptionRecord.setUserId(Integer.parseInt(orderInfo.getUser_id()+""));
            mallOrderExceptionRecord.setOrderSn(orderInfo.getOrder_sn());
            mallOrderExceptionRecord.setExceptionContent(expContent);
            mallOrderExceptionRecord.setExceptionStatus(exceptionStatus);
            mallOrderExceptionRecord.setCreateTime(new Date());
            apiOrderExceptionRecordService.save(mallOrderExceptionRecord);
        }
    }

    /**
     * 微信订单回调接口
     *
     * @return
     */
    @IgnoreAuth
    @RequestMapping(value = "/notify", produces = "text/html;charset=UTF-8")
    @ResponseBody
    public void notify(HttpServletRequest request, HttpServletResponse response) {
        logger.info("微信订单回调接口>>>>>>notify start");
        try {
            request.setCharacterEncoding("UTF-8");
            response.setContentType("text/html;charset=UTF-8");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Access-Control-Allow-Origin", "*");
            InputStream in = request.getInputStream();
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = in.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            out.close();
            in.close();
            String reponseXml = new String(out.toByteArray(), "utf-8");//xml数据
            logger.error("reponseXml:" + reponseXml);
            JSONObject jsonObject = JSONObject.fromObject(reponseXml);
            PayResourceDto payResourceDto = (PayResourceDto)JSONObject.toBean(jsonObject, PayResourceDto.class);

            String event_type = payResourceDto.getEvent_type();
            if (event_type.equalsIgnoreCase("TRANSACTION.SUCCESS")) {
                ResourceDto resourceDto = payResourceDto.getResource();//加密数据对象
                if(resourceDto != null) {
                    String associatedData = resourceDto.getAssociated_data();
                    String nonce = resourceDto.getNonce();
                    String cipherText = resourceDto.getCiphertext();//数据密文
                    String wechatpayCert = AesGcmExampleUtil.aesgcmDecrypt(associatedData, nonce, cipherText);
                    JSONObject certJson = JSONObject.fromObject(wechatpayCert);
                    WechatGlobalUniformNotifyResult result = (WechatGlobalUniformNotifyResult)JSONObject.toBean(certJson, WechatGlobalUniformNotifyResult.class);
                    logger.error("订单 " + result.getOut_trade_no() + " 支付成功");
                    // 业务处理
                    apiWxGlobalPayService.notify(result);
                }
                response.getWriter().write(setXml(WechatGlobalUtil.WXTradeState.SUCCESS.getCode(), "OK"));
                response.getWriter().close();
            } else {
                logger.error("支付失败");
                response.getWriter().write(setXml(WechatGlobalUtil.WXTradeState.SUCCESS.getCode(), "OK"));
                response.getWriter().close();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
    }

    /**
     * 微信订单退款回调接口
     *
     * @return
     */
    @IgnoreAuth
    @RequestMapping(value = "/refundNotify", produces = "text/html;charset=UTF-8")
    @ResponseBody
    public void refundNotify(HttpServletRequest request, HttpServletResponse response) {
        logger.info("微信订单退款回调接口》》》》refundNotify start");
        try {
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/html;charset=UTF-8");
            response.setHeader("Access-Control-Allow-Origin", "*");
            InputStream in = request.getInputStream();
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = in.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            out.close();
            in.close();
            String reponseXml = new String(out.toByteArray(), "utf-8");//xml数据
            reponseXml = reponseXml.replace("\n","").replace("\r","");
            reponseXml = reponseXml+"}}";
            logger.error("reponseXml :" + reponseXml);
            JSONObject jsonObject= JSONObject.fromObject(reponseXml);
            PayResourceDto payResourceDto = (PayResourceDto)JSONObject.toBean(jsonObject, PayResourceDto.class);

            String event_type = payResourceDto.getEvent_type();
            if (event_type.equalsIgnoreCase("REFUND.SUCCESS")) {
                ResourceDto resourceDto = payResourceDto.getResource();//加密数据对象
                if(resourceDto != null) {
                    String associatedData = resourceDto.getAssociated_data();
                    String nonce = resourceDto.getNonce();
                    String cipherText = resourceDto.getCiphertext();//数据密文
                    String wechatpayCert = AesGcmExampleUtil.aesgcmDecrypt(associatedData, nonce, cipherText);
                    JSONObject certJson = JSONObject.fromObject(wechatpayCert);
                    WechatRefundAsynApiResult refundApiResult = (WechatRefundAsynApiResult)JSONObject.toBean(certJson, WechatRefundAsynApiResult.class);
                    logger.error("订单 " + refundApiResult.getOut_trade_no() + "退款成功");
                    // 业务处理
                    apiWxGlobalPayService.refundNotify(refundApiResult);
                    response.getWriter().write(setXml(WechatGlobalUtil.WXTradeState.SUCCESS.getCode(), "OK"));
                }
                response.getWriter().write(setXml(WechatGlobalUtil.WXTradeState.SUCCESS.getCode(), "OK"));
                response.getWriter().close();
            } else {
                logger.info("微信国际退款接口调用失败 ： "+payResourceDto.getSummary());
                response.getWriter().write(setXml(WechatGlobalUtil.WXTradeState.SUCCESS.getCode(), "OK"));
                response.getWriter().close();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
    }

    //返回微信服务
    public static String setXml(String return_code, String return_msg) {
        return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
    }
}