package com.bweb.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bweb.config.SysConst;
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.DateUtil;
import com.hai.common.utils.HttpsUtils;
import com.hai.common.utils.ResponseMsgUtil;
import com.hai.common.utils.WxUtils;
import com.hai.config.*;
import com.hai.dao.HighGasOrderPushMapper;
import com.hai.entity.*;
import com.hai.model.*;
import com.hai.service.*;
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.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.math.BigDecimal;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * @Auther: 胡锐
 * @Description:
 * @Date: 2021/3/26 23:08
 */
@Controller
@RequestMapping(value = "/test")
@Api(value = "订单接口")
public class HighTestController {

    private static Logger log = LoggerFactory.getLogger(HighTestController.class);

    @Resource
    private HltUnionCardVipService hltUnionCardVipService;

    @Resource
    private HighTestService highTestService;

    @Resource
    private OutRechargeOrderService outRechargeOrderService;

    @Resource
    private HighOrderService highOrderService;

    @Resource
    private HighUserService highUserService;

    @Resource
    private SecSinopecConfigService secSinopecConfigService;

    @Resource
    private HighCouponCodeService highCouponCodeService;

    @Resource
    private HighOilCardService oilCardService;

    @Resource
    private GoodsOrderServiceImpl goodsOrderService;

    @Autowired
    private WebSocket webSocket;

    @Resource
    private HighProfitSharingRecordService highProfitSharingRecordService;

    @RequestMapping(value = "/oilCardRefund", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "油卡退款")
    public ResponseData oilCardRefund(@RequestParam(name = "orderNo", required = true) String orderNo,HttpServletRequest request) {
        try {

            oilCardService.refund(orderNo);
            return ResponseMsgUtil.success("");

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

    @RequestMapping(value = "/wxProfitsharing", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "分账")
    public ResponseData wxProfitsharing(@RequestParam(name = "orderNo", required = true) String orderNo) {
        try {
            HighOrder order = highOrderService.getOrderByOrderNo(orderNo);
            BigDecimal rake = new BigDecimal("0.01");
            // 计算微信收取的手续费     支付金额 * 0.002      注：如果与两个相邻数字的距离相等，则为上舍入的舍入模式。
            BigDecimal wxHandlingFee = order.getPayPrice().multiply(new BigDecimal("0.002")).setScale(2,BigDecimal.ROUND_HALF_DOWN);
            BigDecimal price = order.getPayPrice().subtract(wxHandlingFee);

            Map<String,String> param = new LinkedHashMap<>();
            param.put("appid", "wx637bd6f7314daa46");
            param.put("mch_id", "1289663601");
            param.put("sub_mch_id" , "1624126902"); // 渝北区浩联物资经营部
            param.put("transaction_id" , order.getPaySerialNo());
            param.put("out_order_no" , order.getOrderNo());
            param.put("nonce_str" , WxUtils.makeNonStr());

            // 计算分账金额    手续费后的价格 * 0.01  注：如果与两个相邻数字的距离相等，则为上舍入的舍入模式。
            BigDecimal porofitSharingAmount = price.multiply(rake).setScale(2,BigDecimal.ROUND_DOWN);

            List<Map<String,Object>> receiversList = new ArrayList<>();
            Map<String,Object> receiversMap = new LinkedHashMap<>();
            receiversMap.put("type", "MERCHANT_ID");
            receiversMap.put("account", "1603942866");
            receiversMap.put("amount", porofitSharingAmount.multiply(new BigDecimal("100")).intValue());
            receiversMap.put("description", "分给商户【惠昕石化】");
            receiversList.add(receiversMap);
            param.put("receivers" , JSONObject.toJSONString(receiversList));
            String signStr = WxUtils.generateSignature(param, "Skufk5oi85wDFGl888i6wsRSTkdd5df5" , WXPayConstants.SignType.HMACSHA256);
            param.put("sign" , signStr);
            String resultXmL = this.profitsharing(param.get("mch_id"),null, WxUtils.mapToXml(param));

            // 请求分账返回的结果
            ResultProfitSharing resultProfitSharing = XmlUtil.getObjectFromXML(resultXmL, ResultProfitSharing.class);

            HighProfitSharingRecord sharingRecord = new HighProfitSharingRecord();
            sharingRecord.setOutOrderNo(resultProfitSharing.getOut_order_no());
            sharingRecord.setTransactionId(resultProfitSharing.getTransaction_id());
            sharingRecord.setOrderId(resultProfitSharing.getOrder_id());
            sharingRecord.setStatus(resultProfitSharing.getResult_code());
            sharingRecord.setPrice(porofitSharingAmount);
            sharingRecord.setCreateTime(new Date());
            sharingRecord.setContent(resultXmL);
            highProfitSharingRecordService.insert(sharingRecord);

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

        } catch (Exception e) {
            log.error("CmsContentController --> getCorporateAdvertising() error!", e);
            return ResponseMsgUtil.success(e);
        }
    }

    public String profitsharing(String mchId, String url, String data) throws Exception {

        //小程序退款需要调用双向证书的认证
        CloseableHttpClient httpClient = goodsOrderService.readCertificate(mchId);
        try {
            HttpPost httpost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/profitsharing"); // 设置响应头信息
            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 = "/getBackendToken", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "获取访问令牌backendToken")
    public ResponseData getBackendToken() {
        try {
            return ResponseMsgUtil.success(null);
        } catch (Exception e) {
            log.error("HighOrderController --> getBackendToken() error!", e);
            return ResponseMsgUtil.exception(e);
        }
    }

    @RequestMapping(value = "/sys", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "同步")
    public ResponseData sys(@RequestParam(name = "appId", required = true) String appId,
                            @RequestParam(name = "appSecret", required = true) String appSecret,
                            @RequestParam(name = "code", required = true) String code,
                            @RequestParam(name = "signKey", required = true) String signKey
    ) {
        try {
            Map<String, Object> tokenMap = new HashMap<>();
            tokenMap.put("appId", appId);
            tokenMap.put("appSecret", appSecret);
            JSONObject jsonObject = HttpsUtils.doPost("https://app.zshcqsy.com/api-provider/api/open/merchant/token", JSON.toJSONString(tokenMap));
            log.error(jsonObject.toJSONString());

            if (jsonObject != null && jsonObject.getBoolean("success") == true) {
                JSONObject data = jsonObject.getJSONObject("data");
                String token = data.getString("token");

                Calendar instance = Calendar.getInstance();
                instance.set(2021,3,1);

                Map<String,Object> bodyMap = new HashMap<>();
                bodyMap.put("appId", appId);
                bodyMap.put("pageNo", 1);
                bodyMap.put("pageSize", 999999);
                bodyMap.put("startTime", instance.getTime());

                bodyMap.put("endTime", new Date().getTime());
                bodyMap.put("customerCode", code);

                Long date  = new Date().getTime();
                String sha256 = encodeBySHA256(signKey + JSON.toJSONString(bodyMap) + date);
                JSONObject object = HttpsUtils.doPost("https://app.zshcqsy.com/api-provider/sapapi/open/coupon/customerRedeemcodeList", JSON.toJSONString(bodyMap), token, sha256, date);

                File file = new File("/home/data/" + System.currentTimeMillis() + ".txt");
                if (!file.exists()) {
                    file.createNewFile();
                }
                FileWriter fw = new FileWriter(file.getAbsoluteFile());
                BufferedWriter bw = new BufferedWriter(fw);
                bw.write(object.toJSONString());
                bw.close();

                //JSONObject object = JSONObject.parseObject("{\"code\":1000,\"data\":{\"pageNo\":1,\"pageSize\":100,\"rowCount\":\"2\",\"list\":[{\"nodeName\":\"中国石油化工股份有限公司重庆江南石油分公司大学城南二路加油加\",\"totalAmount\":150.00,\"codeId\":\"01DIhbtPzIghPP0mPWaWzO13\",\"nodeNo\":\"50000105\",\"name\":\"重庆惠昕石化有限责任公司11.02日150元券\",\"useTime\":\"2021-04-03 06:11:14\"},{\"nodeName\":\"中国石化销售有限公司重庆三峡分公司忠县经营部三台加油站\",\"totalAmount\":100.00,\"codeId\":\"201126141728001027\",\"nodeNo\":\"50000238\",\"name\":\"重庆惠昕石化有限责任公司11.26日100元券\",\"useTime\":\"2021-04-03 15:16:03\"}]},\"success\":true}");
               if(Objects.equals(object.get("success"), true)) {
                log.error(JSONObject.toJSONString(object.get("data")));

                Object dataJson = JSONObject.parse(JSONObject.toJSONString(object.get("data")));
                JSONObject dataObject = JSON.parseObject(JSONObject.toJSONString(dataJson));
                JSONArray list = dataObject.getJSONArray("list");
                for (Object dataJsonObject : list) {
                    try {
                        JSONObject parseObject = JSON.parseObject(JSON.toJSONString(dataJsonObject));
                        String codeId = parseObject.getString("codeId");
                        String nodeName = parseObject.getString("nodeName");
                        Date useTime = DateUtil.format(parseObject.getString("useTime"), "yyyy-MM-dd HH:mm:ss");
                        highCouponCodeService.cnpcCallbackCouponCode(codeId, useTime, nodeName);
                    } catch (Exception e) {
                        log.error("HighCouponSchedule --> expiredCoupon() error!", e);
                    }
                }
            }
            return ResponseMsgUtil.success("下载成功");
            }
            return ResponseMsgUtil.success(jsonObject);
        } catch (Exception e) {
            log.error("HighOrderController --> getBackendToken() error!", e);
            return ResponseMsgUtil.exception(e);
        }
    }

    public String encodeBySHA256(String str) {
        try{
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.reset();
            messageDigest.update(str.getBytes("UTF-8"));
            return getFormattedText(messageDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return "";
    }

    private static final String[] HEX_DIGITS = {"0" ,"1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};
    private String getFormattedText(byte[] bytes) {
        int len = bytes.length;
        StringBuilder buf = new StringBuilder(len * 2);
        // 把密文转换成十六进制的字符串形式
        for (int j=0;j<len;j++){
            buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
            buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
        }
        return buf.toString();
    }

    @RequestMapping(value = "/GetMembershipLevel", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "请求会员体系")
    public ResponseData GetMembershipLevel(@RequestParam(name = "phone", required = true) String phone , @RequestParam(name = "regionId", required = true) String regionId ) {
        try {
            return ResponseMsgUtil.success(hltUnionCardVipService.GetMembershipLevel(phone , regionId));
        } catch (Exception e) {
            log.error("HighOrderController --> getBackendToken() error!", e);
            return ResponseMsgUtil.exception(e);
        }
    }


    @RequestMapping(value = "/submitSms", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "请求短信")
    public ResponseData submitSms(@RequestParam(name = "phone", required = true) String phone , @RequestParam(name = "sms", required = true) String sms ) {
        try {
            return ResponseMsgUtil.success(HuiLianTongUnionCardConfig.submitSms(phone , sms));
        } catch (Exception e) {
            log.error("HighOrderController --> getBackendToken() error!", e);
            return ResponseMsgUtil.exception(e);
        }
    }


    @RequestMapping(value="/resolveResponse",method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "解析")
    public ResponseData resolveResponse(
            @RequestParam(name = "data", required = false) String data
    ) {
        try {
            JSONObject cardInfoObject = HuiLianTongUnionCardConfig.resolveResponse(data);
            return ResponseMsgUtil.success(cardInfoObject);

        } catch (Exception e) {
            log.error("getUserByTelephone",e);
            return ResponseMsgUtil.exception(e);
        }
    }

    @RequestMapping(value="/getReadFile",method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "存入用户信息")
    public ResponseData getReadFile() {
        try {
            highTestService.getReadFile();
            return ResponseMsgUtil.success(null);
        } catch (Exception e) {
            log.error("getUserByTelephone",e);
            return ResponseMsgUtil.exception(e);
        }
    }


    @RequestMapping(value="/queryAmount",method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "查询余额")
    public ResponseData queryAmount() {
        try {
//            outRechargeOrderService.queryAmount();
            return ResponseMsgUtil.success(null);
        } catch (Exception e) {
            log.error("getUserByTelephone",e);
            return ResponseMsgUtil.exception(e);
        }
    }


    @RequestMapping(value = "/getHuiLianTongCardConsume", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "查询汇联通工会卡消费记录")
    public ResponseData getHuiLianTongCardConsume(@RequestParam(name = "businessType", required = true) String businessType,
                                                  @RequestParam(name = "cardNo", required = true) String cardNo,
                                                  @RequestParam(name = "sdate", required = true) Long sdate,
                                                  @RequestParam(name = "edate", required = true) Long edate,
                                                  @RequestParam(name = "pageNum", required = true) Integer pageNum,
                                                  @RequestParam(name = "pageSize", required = true) Integer pageSize,
                                                  HttpServletRequest request) {
        try {


            JSONObject consumptionRecord = HuiLianTongUnionCardConfig.queryConsumptionRecordByBusiness(businessType, cardNo, sdate, edate, pageNum, pageSize);
            if (StringUtils.isBlank(consumptionRecord.getString("data"))) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.REQUEST_ERROR, "");
            }

            return ResponseMsgUtil.success(HuiLianTongUnionCardConfig.resolveResponse(consumptionRecord.getString("data")));

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

    @RequestMapping(value = "/orderToRefund", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "积分充值退款")
    public ResponseData orderToRefund(@RequestParam(name = "orderId", required = true) Long orderId ,HttpServletRequest request) {
        try {
            HighOrder highOrder = highOrderService.getOrderById(orderId);
            // 微信退款
            OrderRefundModel orderRefundModel = WxOrderConfig.orderToRefund(highOrder.getPaySerialNo(), highOrder.getPayRealPrice(), highOrder.getPayRealPrice());
            if(orderRefundModel.getResult_code().equals("SUCCESS")) {
                for (HighChildOrder childOrder : highOrder.getHighChildOrderList()) {
                    childOrder.setChildOrdeStatus(4);
                }
                highOrder.setOrderStatus(4);
                highOrder.setRefundTime(new Date());
                highOrder.setRefundPrice(highOrder.getPayRealPrice());
                highOrderService.updateOrder(highOrder);
            }
            if (highUserService.findGoldRepeat(3 , highOrder.getId())) {
                highUserService.goldHandle(highOrder.getMemId(), highOrder.getPayRealPrice().multiply(BigDecimal.valueOf(100)).intValue(), 2, 3, highOrder.getId());
            }else {
                log.error("orderToPay error!", "已有退款记录");
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "已有退款记录");
            }
            return ResponseMsgUtil.success(orderRefundModel);

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

    @RequestMapping(value = "/orderToRefundByHlt", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "汇联通充值退款")
    public ResponseData orderToRefundByHlt(@RequestParam(name = "orderId", required = true) Long orderId ,HttpServletRequest request) {
        try {
            HighOrder highOrder = highOrderService.getOrderById(orderId);
            // 微信退款
            OrderRefundModel orderRefundModel = WxOrderConfig.orderToRefund(highOrder.getPaySerialNo(), highOrder.getPayRealPrice(), WxOrderConfig.MCH_ID_1619676214 , highOrder.getPayRealPrice());
            if(orderRefundModel.getResult_code().equals("SUCCESS")) {
                for (HighChildOrder childOrder : highOrder.getHighChildOrderList()) {
                    childOrder.setChildOrdeStatus(4);
                }
                highOrder.setOrderStatus(4);
                highOrder.setRefundTime(new Date());
                highOrder.setRefundPrice(highOrder.getPayRealPrice());
                highOrderService.updateOrder(highOrder);
            }
            return ResponseMsgUtil.success(orderRefundModel);

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


    @RequestMapping(value = "/zwrefund", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "银联退款")
    public ResponseData zwrefund(
            @RequestParam(name = "orderId", required = true) Long orderId ,
            @RequestParam(name = "MER_ID", required = true) String MER_ID ,
            @RequestParam(name = "TERM_ID", required = true) String TERM_ID ,
            HttpServletRequest request) {
        try {

            OutRechargeOrder order = outRechargeOrderService.findByOrderId(orderId);
            // 订单退款
            JSONObject refund = UnionPayConfig.zwrefund(MER_ID, TERM_ID, order.getOrderNo(), order.getPaySerialNo(), order.getPayRealPrice().multiply(new BigDecimal("100")).longValue());
            if (!refund.getString("resultcode").equals("W6")) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, refund.getString("returnmsg"));
            }

            order.setStatus(5);
            order.setRefundTime(new Date());
            order.setOutRefundNo(refund.getString("oriwtorderid"));
            order.setRefundFee(order.getPayRealPrice());
            outRechargeOrderService.updateOrder(order);
            return ResponseMsgUtil.success(refund);

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

    @RequestMapping(value = "/rechargeOrderToRefund", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "话费退款")
    public ResponseData rechargeOrderToRefund(
            @RequestParam(name = "orderId", required = true) Long orderId) {
        try {
            outRechargeOrderService.rechargeOrderToRefund(orderId);

            return ResponseMsgUtil.success("退款成功");

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


    @RequestMapping(value = "/findByLatAndLng", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "获取定位信息")
    public ResponseData findByLatAndLng(
            @RequestParam(name = "lng", required = true) String lng,
            @RequestParam(name = "lat", required = true) String lat
    ) {
        try {

            return ResponseMsgUtil.success(highTestService.findByLatAndLng(lng , lat));

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


    @RequestMapping(value = "/websocket", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "websocket")
    public ResponseData websocket(
            @RequestParam(name = "userId", required = true) String userid,
            @RequestParam(name = "message", required = true) String message
    ) {
        try {

            webSocket.SenderMessage(userid ,message);
            return ResponseMsgUtil.success("null");

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


}
