package com.kmall.api.api.wxGlobal;

import com.google.common.collect.Maps;
import com.kmall.api.annotation.IgnoreAuth;
import com.kmall.api.annotation.LoginUser;
import com.kmall.api.entity.cus.pay.data.open.CusPayDataOpenVo;
import com.kmall.api.service.cus.pay.data.open.ApiCusPayDataOpenService;
import com.kmall.manager.manager.wechat.AESUtil;
import com.kmall.manager.manager.wechat.WechatGlobalUtil;
import com.kmall.manager.manager.wechat.WechatUtil;
import com.kmall.manager.manager.wechat.wxglobal.dto.WechatGlobalNotifyResult;
import com.kmall.manager.manager.wechat.wxglobal.dto.WechatGlobalQueryApiResult;
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.WechatRefundApiResult;
import com.kmall.common.utils.wechat.WechatRefundNotifyResult;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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 Log logger = LogFactory.getLog(ApiWxGlobalPayController.class);
    @Autowired
    private ApiOrderService orderService;
    @Autowired
    private ApiOrderGoodsService orderGoodsService;
    @Autowired
    private ApiWxGlobalPayService apiWxGlobalPayService;
    @Autowired
    private ApiOrderProcessRecordService orderProcessRecordService;
    @Autowired
    private ApiOrderExceptionRecordService apiOrderExceptionRecordService;
    @Autowired
    private ApiCusPayDataOpenService cusPayDataOpenService;

    /**
     * 发起支付
     * @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;
        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());
        }
        String nonceStr = CharUtil.getRandomString(32);
        Map<Object, Object> resultObj = Maps.newHashMap();

        try {
            //订单的商品
            List<OrderGoodsVo> orderGoods = orderGoodsService.queryListByIds(orderIdList);
            String body = "";
            if (null != orderGoods) {
                body = "商城-";
                for (OrderGoodsVo goodsVo : orderGoods) {
                    body = body + goodsVo.getGoods_name() + "、";
                }
                if (body.length() > 0) {
                    body = body.substring(0, body.length() - 1);
                }
            }
            //统一下单
            WechatGlobalQueryApiResult queryApiResult = WechatGlobalUtil.unifiedOrder(merchOrderSn, body, actual_price, loginUser.getWeixin_openid());
            // 响应报文
            String return_code = queryApiResult.getReturn_code();
            String return_msg = queryApiResult.getReturn_msg();
            //
            if (return_code.equalsIgnoreCase("FAIL")) {
//                updateFailProcessBatch(processRecordEntityList, "支付失败 ," +return_msg);//更新订单流转信息
                addOrderExceptionRecord(orderVoList, Dict.exceptionStatus.item_00.getItem(),"支付失败 ," +return_msg);//记录订单异常信息
                return toResponsFail("支付失败 ," + return_msg);
            } else if (return_code.equalsIgnoreCase(WechatUtil.WXTradeState.SUCCESS.getCode())) {
                // 返回数据
                String result_code = queryApiResult.getResult_code();
                String err_code_des = queryApiResult.getErr_code_des();
                if (result_code.equalsIgnoreCase("FAIL")) {
//                    updateFailProcessBatch(processRecordEntityList, "支付失败 ," +err_code_des);//更新订单流转信息
                    addOrderExceptionRecord(orderVoList, Dict.exceptionStatus.item_00.getItem(),"支付失败 ," +err_code_des);//记录订单异常信息
                    return toResponsFail("支付失败 ," + err_code_des);
                } else if (result_code.equalsIgnoreCase(WechatGlobalUtil.WXTradeState.SUCCESS.getCode())) {
                    // 添加信息
                    for (OrderVo orderInfo: orderVoList) {
                        if(!orderInfo.getOrderBizType().equalsIgnoreCase(Dict.orderBizType.item_11.getItem())) {
                            CusPayDataOpenVo cusPayDataOpen = cusPayDataOpenService.queryObjectByOrderNo(orderInfo.getOrder_sn());
                            if (cusPayDataOpen == null) {
                                cusPayDataOpen = new CusPayDataOpenVo();
                                cusPayDataOpen.setMerchOrderSn(merchOrderSn);
                                cusPayDataOpen.setOrderNo(orderInfo.getOrder_sn());
                                cusPayDataOpen.setInitalRequest(queryApiResult.getXml());
                                cusPayDataOpen.setCreateTime(new Date());
                                cusPayDataOpen.setModTime(new Date());
                                cusPayDataOpenService.save(cusPayDataOpen);
                            } else {
                                cusPayDataOpen.setMerchOrderSn(merchOrderSn);
                                cusPayDataOpen.setInitalRequest(queryApiResult.getXml());
                                cusPayDataOpen.setModTime(new Date());
                                cusPayDataOpenService.update(cusPayDataOpen);
                            }
                        }
                    }
                    apiWxGlobalPayService.payPrepay(resultObj, queryApiResult, nonceStr, orderVoList);
                    orderProcessRecordService.updateBatch(processRecordEntityList);//更新订单流转信息
                    return toResponsObject(0, "微信统一订单下单成功", resultObj);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
//            updateFailProcessBatch(processRecordEntityList, "下单失败,error=" + e.getMessage());//更新订单流转信息
            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);
            WechatGlobalNotifyResult result = (WechatGlobalNotifyResult) XmlUtil.xmlStrToBean(reponseXml, WechatGlobalNotifyResult.class);
            String result_code = result.getResult_code();
            String out_trade_no = result.getOut_trade_no();//订单编号
            if (result_code.equalsIgnoreCase("FAIL")) {
                logger.error("订单 " + out_trade_no + " 支付失败");
                response.getWriter().write(setXml(WechatGlobalUtil.WXTradeState.SUCCESS.getCode(), "OK"));
                response.getWriter().close();
            } else if (result_code.equalsIgnoreCase(WechatGlobalUtil.WXTradeState.SUCCESS.getCode())) {
                logger.error("订单 " + out_trade_no + " 支付成功");
                // 业务处理
                apiWxGlobalPayService.notify(result);
                response.getWriter().write(setXml(WechatGlobalUtil.WXTradeState.SUCCESS.getCode(), "OK"));
            }
        } 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数据
            logger.error("reponseXml :" + reponseXml);
            WechatRefundNotifyResult result = (WechatRefundNotifyResult) XmlUtil.xmlStrToBean(reponseXml, WechatRefundNotifyResult.class);

            if (result.getReturn_code().equalsIgnoreCase("FAIL")) {
                logger.info("微信查询接口调用失败 ： "+result.getReturn_msg());
                response.getWriter().write(setXml(WechatGlobalUtil.WXTradeState.SUCCESS.getCode(), "OK"));
                response.getWriter().close();
            }else {
                String req_info = result.getReq_info();//加密信息
                String aesResult = AESUtil.decryptData(req_info);
                System.out.println(aesResult);
                WechatRefundApiResult refundApiResult = (WechatRefundApiResult) XmlUtil.xmlStrToBean(aesResult, WechatRefundApiResult.class);

                logger.error("订单 " + refundApiResult.getOut_trade_no() + "退款成功");
                // 业务处理
                apiWxGlobalPayService.refundNotify(refundApiResult);
                response.getWriter().write(setXml(WechatGlobalUtil.WXTradeState.SUCCESS.getCode(), "OK"));
            }

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