package com.bweb.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSONObject;
import com.bweb.config.SysConst;
import com.bweb.model.ExportOutRechargeOrder;
import com.bweb.model.ExportOutRechargeOrderCount;
import com.bweb.model.ExportOutRechargeUserOrderCount;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hai.common.exception.ErrorCode;
import com.hai.common.exception.ErrorHelp;
import com.hai.common.exception.SysCode;
import com.hai.common.pay.util.XmlUtil;
import com.hai.common.pay.util.sdk.WXPayConstants;
import com.hai.common.utils.ResponseMsgUtil;
import com.hai.common.utils.WxUtils;
import com.hai.config.HuiLianTongUnionCardConfig;
import com.hai.entity.HighRefundAudit;
import com.hai.entity.OutRechargeOrder;
import com.hai.model.*;
import com.hai.service.HighRefundAuditService;
import com.hai.service.OutRechargeOrderService;
import com.hai.service.pay.impl.GoodsOrderServiceImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping(value = "/outRechargeOrder")
@Api(value = "充值订单接口")
public class OutRechargeOrderController {
    private static Logger log = LoggerFactory.getLogger(HighMerchantStoreController.class);

    @Resource
    private OutRechargeOrderService outRechargeOrderService;


    @Resource
    private GoodsOrderServiceImpl goodsOrderService;

    @Resource
    private HighRefundAuditService highRefundAuditService;


    @RequestMapping(value = "/getOrderById", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "根据id查询订单详情")
    public ResponseData getOrderById(@RequestParam(name = "orderId", required = true) Long orderId) {
        try {

            return ResponseMsgUtil.success(outRechargeOrderService.findByOrderId(orderId));

        } catch (Exception e) {
            log.error("HighOrderController --> getOrderById() error!", e);
            return ResponseMsgUtil.exception(e);
        }
    }

    @RequestMapping(value = "/cancelOrder", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "取消订单")
    public ResponseData cancelOrder(@RequestParam(name = "orderId", required = true) Long orderId) {
        try {

            OutRechargeOrder outRechargeOrder  = outRechargeOrderService.findByOrderId(orderId);

            if (outRechargeOrder.getStatus() == 1) {
                outRechargeOrderService.cancelOrder(orderId);
            } else {
                log.error("orderToPay error!");
                throw ErrorHelp.genException(SysCode.System, ErrorCode.STATUS_ERROR, "");
            }

            return ResponseMsgUtil.success("操作成功");

        } catch (Exception e) {
            log.error("HighOrderController --> cancelOrder() error!", e);
            return ResponseMsgUtil.exception(e);
        }
    }

    @RequestMapping(value = "/finishOrder", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "完成充值")
    public ResponseData finishOrder(@RequestParam(name = "orderId", required = true) Long orderId) {
        try {

            OutRechargeOrder outRechargeOrder  = outRechargeOrderService.findByOrderId(orderId);

            if (outRechargeOrder.getStatus() == 2) {
                outRechargeOrderService.finishOrder(orderId);
            } else {
                log.error("orderToPay error!");
                throw ErrorHelp.genException(SysCode.System, ErrorCode.STATUS_ERROR, "");
            }

            return ResponseMsgUtil.success("操作成功");

        } catch (Exception e) {
            log.error("HighOrderController --> cancelOrder() error!", e);
            return ResponseMsgUtil.exception(e);
        }
    }

    @RequestMapping(value = "/getOrderList", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "获取订单")
    public ResponseData getUserOrderList(
            @RequestParam(name = "status", required = false) Integer status,
            @RequestParam(name = "orderNo", required = false) String orderNo,
            @RequestParam(name = "rechargeModel", required = false) String rechargeModel,
            @RequestParam(name = "rechargeContent", required = false) String rechargeContent,
            @RequestParam(name = "userPhone", required = false) String userPhone,
            @RequestParam(name = "payType", required = false) Integer payType,
            @RequestParam(name = "code", required = false) Integer code,
            @RequestParam(name = "payTimeS", required = false) Long payTimeS,
            @RequestParam(name = "payTimeE", required = false) Long payTimeE,
            @RequestParam(name = "pageNum", required = true) Integer pageNum,
            @RequestParam(name = "pageSize", required = true) Integer pageSize,
            HttpServletRequest request) {
        try {

            Map<String,String> map = new HashMap<>();

            if (status != null) {
                map.put("status", status.toString());
            }
            if (StringUtils.isNotBlank(orderNo)) {
                map.put("orderNo", orderNo);
            }
            if (StringUtils.isNotBlank(rechargeModel)) {
                map.put("rechargeModel", rechargeModel);
            }

            if (StringUtils.isNotBlank(rechargeContent)) {
                map.put("rechargeContent", rechargeContent);
            }

            if (StringUtils.isNotBlank(userPhone)) {
                map.put("userPhone", userPhone);
            }
            if (payType != null) {
                map.put("payType" , payType.toString());
            }
            if (code != null) {
                map.put("code" , code.toString());
            }
            if (payTimeS != null) {
                map.put("payTimeS", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(payTimeS));
            }
            if (payTimeE != null) {
                map.put("payTimeE", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(payTimeE));
            }

            PageHelper.startPage(pageNum,pageSize);
            return ResponseMsgUtil.success(new PageInfo<>(outRechargeOrderService.getListRechargeOrder(map)));

        } catch (Exception e) {
            log.error("HighOrderController --> getUserOrderList() error!", e);
            return ResponseMsgUtil.exception(e);
        }
    }

    @RequestMapping(value = "/countOrder", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "完成充值")
    public ResponseData countOrder() {
        try {

            return ResponseMsgUtil.success(outRechargeOrderService.CountOrder());

        } catch (Exception e) {
            log.error("HighOrderController --> cancelOrder() error!", e);
            return ResponseMsgUtil.exception(e);
        }
    }

    @RequestMapping(value = "/exportOrderList", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "导出订单")
    public ResponseData exportOrderList(@RequestParam(name = "status", required = false) Integer status,
                                        @RequestParam(name = "orderNo", required = false) String orderNo,
                                        @RequestParam(name = "rechargeModel", required = false) String rechargeModel,
                                        @RequestParam(name = "rechargeContent", required = false) String rechargeContent,
                                        @RequestParam(name = "userPhone", required = false) String userPhone,
                                        @RequestParam(name = "payType", required = false) Integer payType,
                                        @RequestParam(name = "code", required = false) Integer code,
                                        @RequestParam(name = "createTimeS", required = false) Long createTimeS,
                                        @RequestParam(name = "createTimeE", required = false) Long createTimeE,
                                        @RequestParam(name = "payTimeS", required = false) Long payTimeS,
                                        @RequestParam(name = "payTimeE", required = false) Long payTimeE) {
        try {

            Map<String,Object> map = new HashMap<>();
            map.put("status", status);
            map.put("orderNo", orderNo);
            map.put("rechargeModel", rechargeModel);
            map.put("rechargeContent", rechargeContent);
            map.put("userPhone", userPhone);
            map.put("payType", payType);
            map.put("code", code);
            map.put("createTimeS", createTimeS);
            map.put("createTimeE", createTimeE);
            map.put("payTimeS", payTimeS);
            map.put("payTimeE", payTimeE);
            List<OutRechargeOrderModel> list = outRechargeOrderService.getOrderCount(map);

            String name = "/outRechargeOrder/充值订单" + System.currentTimeMillis() + ".xlsx";
            String fileName = SysConst.getSysConfig().getFileUrl() + name;
            EasyExcel.write(fileName, ExportOutRechargeOrder.class).sheet("充值订单").doWrite(list);
            return ResponseMsgUtil.success(name);
        } catch (Exception e) {
            log.error("HighOrderController --> exportOrderList() error!", e);
            return ResponseMsgUtil.exception(e);
        }
    }

    @RequestMapping(value = "/orderToRefund", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "订单退款")
    public ResponseData orderToRefund(@RequestParam(name = "orderId", required = false) Long orderId,
                                      HttpServletRequest request) {
        try {

            OutRechargeOrder order = outRechargeOrderService.findByOrderId(orderId);

            HighRefundAudit highRefundAudit = highRefundAuditService.findByOrderNo(order.getOrderNo());

            if (order == null) {
                log.error("orderToPay error!", "未找到充值订单");
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未找到充值订单");
            }

            // 订单状态 ： 1.待支付 2.已支付 3.已完成 4.已取消 5.已退款 6：退款中
            if (order.getStatus() != 6) {
                log.error("orderToPay error!", "无法退款，订单不处于退款中状态");
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "无法退款，订单不处于已支付状态");
            }

            if (order.getPayType() == 2) {
                JSONObject jsonObject = HuiLianTongUnionCardConfig.refund( "HFR"+new Date().getTime() , order.getOrderNo());
                JSONObject dataObject = HuiLianTongUnionCardConfig.resolveResponse(jsonObject.getString("data"));

                if (dataObject.getBoolean("success")) {
                    order.setStatus(5);
                    order.setRefundTime(new Date());
                    order.setOutRefundNo("HFR"+new Date().getTime() );
                    order.setRefundFee(order.getPayRealPrice());
                    order.setRefundId(dataObject.getString("orderId"));

                    highRefundAudit.setStatus(1);
                    highRefundAuditService.updateRefundAudit(highRefundAudit);
                    outRechargeOrderService.updateOrder(order);
                    return ResponseMsgUtil.success("退款成功");
                } else {
                    log.error("orderToPay error!", dataObject.getString("message"));
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, dataObject.getString("message"));
                }

            } else {
                Map<String,String> param = new HashMap<>();
                param.put("appid", "wx637bd6f7314daa46");
                param.put("mch_id", "1289663601");
                param.put("sub_mch_id" , "1614670195");
                param.put("nonce_str", WxUtils.makeNonStr());
                param.put("transaction_id", order.getPaySerialNo());
                param.put("out_refund_no", "HFR"+new Date().getTime());
                param.put("total_fee", String.valueOf(order.getPayRealPrice().multiply(new BigDecimal("100")).intValue()));
                param.put("refund_fee", String.valueOf(order.getPayRealPrice().multiply(new BigDecimal("100")).intValue()));
                param.put("sign_type", "HMAC-SHA256");

                String signStr = WxUtils.generateSignature(param, "Skufk5oi85wDFGl888i6wsRSTkdd5df5" , WXPayConstants.SignType.HMACSHA256);
                param.put("sign", signStr);

                String resultXmL = doRefundRequest(param.get("mch_id"), WxUtils.mapToXml(param));
                OrderRefundModel orderRefundModel = XmlUtil.getObjectFromXML(resultXmL, OrderRefundModel.class);
                if(orderRefundModel.getResult_code().equals("SUCCESS")) {
                    order.setStatus(5);
                    order.setRefundTime(new Date());
                    order.setOutRefundNo(orderRefundModel.getOut_refund_no());
                    order.setRefundId(orderRefundModel.getRefund_id());
                    order.setRefundFee(new BigDecimal(orderRefundModel.getRefund_fee()).divide(new BigDecimal("100")));
                    outRechargeOrderService.updateOrder(order);
                    highRefundAudit.setStatus(1);
                    highRefundAuditService.updateRefundAudit(highRefundAudit);
                    return ResponseMsgUtil.success("退款成功");
                } else {
                    log.error("orderToPay error!", "退款失败");
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "退款失败！错误代码："+orderRefundModel.getErr_code()+",错误描述"+orderRefundModel.getErr_code_des());
                }
            }

        } catch (Exception e) {
            log.error("HighOrderController --> getUserOrderList() error!", e);
            return ResponseMsgUtil.exception(e);
        }
    }

    public String doRefundRequest(String mchId,String data) throws Exception {

        //小程序退款需要调用双向证书的认证
        CloseableHttpClient httpClient = goodsOrderService.readCertificate(mchId);
        try {
            HttpPost httpost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund"); // 设置响应头信息
            httpost.addHeader("Connection", "keep-alive");
            httpost.addHeader("Accept", "*/*");
            httpost.addHeader("Content-Type", "text/xml");
            httpost.addHeader("Host", "api.mch.weixin.qq.com");
            httpost.addHeader("X-Requested-With", "XMLHttpRequest");
            httpost.addHeader("Cache-Control", "max-age=0");
            httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
            httpost.setEntity(new StringEntity(data, "UTF-8"));
            CloseableHttpResponse response = httpClient.execute(httpost);
            try {
                HttpEntity entity = response.getEntity();
                String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
                EntityUtils.consume(entity);
                return jsonStr;
            } finally {
                response.close();
            }
        } catch (Exception e){
            throw new RuntimeException(e);
        } finally {
            httpClient.close();
        }
    }

    @RequestMapping(value = "/getOrderCountList", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "查询时间订单统计")
    public ResponseData getOrderCountList(
                                          @RequestParam(name = "finishTimeS", required = false) Long finishTimeS,
                                          @RequestParam(name = "finishTimeE", required = false) Long finishTimeE,
                                          @RequestParam(name = "status", required = false) Integer status,
                                          @RequestParam(name = "pageNum", required = true) Integer pageNum,
                                          @RequestParam(name = "pageSize", required = true) Integer pageSize,
                                          HttpServletRequest request) {
        try {

            Map<String,String> map = new HashMap<>();

            if (finishTimeS != null){
                map.put("finishTimeS", finishTimeS.toString());
            }

            if (finishTimeE != null){
                map.put("finishTimeE", finishTimeE.toString());
            }
            if (status != null){
                map.put("status", status.toString());
            }

            PageHelper.startPage(pageNum,pageSize);
            return ResponseMsgUtil.success(new PageInfo<>(outRechargeOrderService.getListOrderCount(map)));

        } catch (Exception e) {
            log.error("HighOrderController --> getUserOrderList() error!", e);
            return ResponseMsgUtil.exception(e);
        }
    }

    @RequestMapping(value = "/exportOrderListCount", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "导出订单")
    public ResponseData exportOrderListCount(@RequestParam(name = "finishTimeS", required = false) Long finishTimeS,
                                             @RequestParam(name = "status", required = false) Integer status,
                                             @RequestParam(name = "finishTimeE", required = false) Long finishTimeE) {
        try {

            Map<String,String> map = new HashMap<>();

            if (finishTimeS != null){
                map.put("finishTimeS", finishTimeS.toString());
            }

            if (finishTimeE != null){
                map.put("finishTimeE", finishTimeE.toString());
            }
            if (status != null){
                map.put("status", status.toString());
            }

            List<OutOrderModel> list = outRechargeOrderService.getListOrderCount(map);

            String name = "/outRechargeOrder/订单统计" + System.currentTimeMillis() + ".xlsx";
            String fileName = SysConst.getSysConfig().getFileUrl() + name;
            EasyExcel.write(fileName, ExportOutRechargeOrderCount.class).sheet("订单统计").doWrite(list);
            return ResponseMsgUtil.success(name);
        } catch (Exception e) {
            log.error("HighOrderController --> exportOrderList() error!", e);
            return ResponseMsgUtil.exception(e);
        }
    }

    @RequestMapping(value = "/getUserCountList", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "查询员工订单统计")
    public ResponseData getUserCountList(
            @RequestParam(name = "finishTimeS", required = false) Long finishTimeS,
            @RequestParam(name = "finishTimeE", required = false) Long finishTimeE,
            @RequestParam(name = "pageNum", required = true) Integer pageNum,
            @RequestParam(name = "pageSize", required = true) Integer pageSize,
            HttpServletRequest request) {
        try {

            Map<String,String> map = new HashMap<>();

            if (finishTimeS != null){
                map.put("finishTimeS", finishTimeS.toString());
            }

            if (finishTimeE != null){
                map.put("finishTimeE", finishTimeE.toString());
            }

            PageHelper.startPage(pageNum,pageSize);
            return ResponseMsgUtil.success(new PageInfo<>(outRechargeOrderService.getUserCountList(map)));

        } catch (Exception e) {
            log.error("HighOrderController --> getUserOrderList() error!", e);
            return ResponseMsgUtil.exception(e);
        }
    }

    @RequestMapping(value = "/exportUserOrderListCount", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "导出员工订单")
    public ResponseData exportUserOrderListCount(@RequestParam(name = "finishTimeS", required = false) Long finishTimeS,
                                             @RequestParam(name = "finishTimeE", required = false) Long finishTimeE) {
        try {

            Map<String,String> map = new HashMap<>();

            if (finishTimeS != null){
                map.put("finishTimeS", finishTimeS.toString());
            }

            if (finishTimeE != null){
                map.put("finishTimeE", finishTimeE.toString());
            }

            List<OutUserOrderModel> list = outRechargeOrderService.getUserCountList(map);

            String name = "/outRechargeOrder/员工订单统计" + System.currentTimeMillis() + ".xlsx";
            String fileName = SysConst.getSysConfig().getFileUrl() + name;
            EasyExcel.write(fileName, ExportOutRechargeUserOrderCount.class).sheet("订单统计").doWrite(list);
            return ResponseMsgUtil.success(name);
        } catch (Exception e) {
            log.error("HighOrderController --> exportOrderList() error!", e);
            return ResponseMsgUtil.exception(e);
        }
    }

}
