package com.hai.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
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.security.AESEncodeUtil;
import com.hai.common.utils.*;
import com.hai.config.*;
import com.hai.dao.HighGasOrderPushMapper;
import com.hai.dao.OutRechargeOrderMapper;
import com.hai.dao.OutRechargeOrderMapperExt;
import com.hai.entity.*;
import com.hai.enum_type.DiscountUseScope;
import com.hai.enum_type.OperatorEnum;
import com.hai.enum_type.OrderPushType;
import com.hai.enum_type.RechargePayType;
import com.hai.model.*;
import com.hai.service.*;
import com.hai.service.pay.impl.GoodsOrderServiceImpl;
import io.swagger.models.auth.In;
import org.apache.commons.collections4.MapUtils;
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.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service("outRechargeOrderService")
public class OutRechargeOrderServiceImpl implements OutRechargeOrderService {

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

    @Resource
    private OutRechargeOrderMapper outRechargeOrderMapper;

    @Resource
    private OutRechargeOrderMapperExt outRechargeOrderMapperExt;

    @Resource
    private HighUserCardService highUserCardService;

    @Resource
    private HighGasOrderPushMapper highGasOrderPushMapper;

    @Resource
    private HighUserService highUserService;

    @Resource
    private OutRechargeOrderService outRechargeOrderService;

    @Resource
    private OutRechargePriceService outRechargePriceService;

    @Resource
    private GoodsOrderServiceImpl goodsOrderService;

    @Resource
    private BsIntegralRebateService bsIntegralRebateService;

    @Resource
    private HighDiscountUserRelService highDiscountUserRelService;

    @Resource
    private HighDiscountAgentCodeService highDiscountAgentCodeService;

    @Resource
    private OutRechargeChildOrderService outRechargeChildOrderService;

    @Resource
    private BsRequestRecordService bsRequestRecordService;

    @Resource
    private BsConfigService bsConfigService;

    @Resource
    private SecConfigService secConfigService;

    @Resource
    private HighUserPayPasswordService highUserPayPasswordService;

    @Resource
    private ApiMerchantsService apiMerchantsService;

    @Resource
    private HighGoldRecService highGoldRecService;

    @Resource
    private ApiAmountRecordService apiAmountRecordService;

    @Resource
    private ApiOrderRecordService apiOrderRecordService;

    @Resource
    private BsRechargeCodeService rechargeCodeService;

    @Override
    public List<OutRechargeOrder> getListRechargeOrder(Map<String, Object> map) {
        OutRechargeOrderExample example = new OutRechargeOrderExample();
        OutRechargeOrderExample.Criteria criteria = example.createCriteria();

        if (MapUtils.getLong(map, "userId") != null) {
            criteria.andUserIdEqualTo(MapUtils.getLong(map, "userId"));
        }
        if (MapUtils.getLong(map, "companyId") != null) {
            criteria.andCompanyIdEqualTo(MapUtils.getLong(map, "companyId"));
        }
        if (MapUtils.getInteger(map, "payType") != null) {
            criteria.andPayTypeEqualTo(MapUtils.getInteger(map, "payType"));
        }
        if (MapUtils.getInteger(map, "laborUnionCard") != null) {
            criteria.andLaborUnionCardEqualTo(MapUtils.getString(map, "laborUnionCard"));
        }
        if (MapUtils.getInteger(map, "payStatus") != null) {
            criteria.andPayStatusEqualTo(MapUtils.getInteger(map, "payStatus"));
        }
        if (MapUtils.getInteger(map, "rechargeType") != null) {
            criteria.andRechargeTypeEqualTo(MapUtils.getInteger(map, "rechargeType"));
        }
        if (MapUtils.getString(map, "orderNo") != null) {
            criteria.andOrderNoLike("%" + MapUtils.getString(map, "orderNo") + "%");
        }
        if (MapUtils.getString(map, "userPhone") != null) {
            criteria.andUserPhoneEqualTo(MapUtils.getString(map, "userPhone"));
        }
        if (MapUtils.getString(map, "rechargeContent") != null) {
            criteria.andRechargeContentLike("%" + MapUtils.getString(map, "rechargeContent") + "%");
        }
        if (MapUtils.getInteger(map, "operatorType") != null) {
            criteria.andOperatorTypeEqualTo(MapUtils.getInteger(map, "operatorType"));
        }
        if (MapUtils.getString(map, "merchId") != null) {
            criteria.andMerchIdEqualTo(MapUtils.getString(map, "merchId"));
        }

        if (MapUtils.getInteger(map, "rechargeStatus") != null) {
            criteria.andRechargeStatusEqualTo(MapUtils.getInteger(map, "rechargeStatus"));
        }
        if (StringUtils.isNotBlank(MapUtils.getString(map, "payTimeS")) && StringUtils.isNotBlank(MapUtils.getString(map, "payTimeE"))) {
            criteria.andPayTimeBetween(
                    DateUtil.format(MapUtils.getString(map, "payTimeS"), "yyyy-MM-dd HH:mm:ss"),
                    DateUtil.format(MapUtils.getString(map, "payTimeE"), "yyyy-MM-dd HH:mm:ss"));
        }
        if (StringUtils.isNotBlank(MapUtils.getString(map, "createTimeS")) && StringUtils.isNotBlank(MapUtils.getString(map, "createTimeE"))) {
            criteria.andCreateTimedBetween(
                    DateUtil.format(MapUtils.getString(map, "createTimeS"), "yyyy-MM-dd HH:mm:ss"),
                    DateUtil.format(MapUtils.getString(map, "createTimeE"), "yyyy-MM-dd HH:mm:ss"));
        }

        example.setOrderByClause("create_timed desc");
        return outRechargeOrderMapper.selectByExample(example);
    }

    @Override
    public OutRechargeOrder findByOrderId(Long orderId) {
        return outRechargeOrderMapper.selectByPrimaryKey(orderId);
    }

    @Override
    public OutRechargeOrder findByOrderNo(String orderNo) {
        OutRechargeOrderExample example = new OutRechargeOrderExample();
        example.createCriteria().andOrderNoEqualTo(orderNo);
        return outRechargeOrderMapper.selectByExample(example).get(0);
    }

    @Override
    @Transactional(
            isolation = Isolation.SERIALIZABLE,
            propagation = Propagation.REQUIRES_NEW)
    public OutRechargeOrder insertOrder(JSONObject object) throws Exception {

        OutRechargeOrder outRechargeOrder = new OutRechargeOrder();

        HighUser user = highUserService.findByUserId(object.getLong("userId"));

        // 产品id
        Long goodsId = object.getLong("goodsId");

        // 充值内容
        String rechargeContent = object.getString("rechargeContent");

        // 查询产品详情
        OutRechargePriceModel outRechargePrice = outRechargePriceService.findById(goodsId, null);

        Map<String, Object> listMap = new HashMap<>();
        listMap.put("productType", "3");
        listMap.put("returnType", 1);
        listMap.put("sourceId", goodsId);

        // 查询产品积分抵扣比例
        BsProductDiscount bsProductDiscount = bsConfigService.getProductDiscountByMap(listMap);

        // 判断充值系统是否关闭
        if (!secConfigService.isConfig("RECHARGE", "1")) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.RECHARGE_CLOSE, "");
        }

        HighDiscountUserRel highDiscountUserRel = null;
        // 判断是否有优惠券
        if (object.getLong("memDiscountId") != null) {
            outRechargeOrder.setMemDiscountId(object.getLong("memDiscountId"));
            // 卡优惠券信息
            highDiscountUserRel = highDiscountUserRelService.getRelById(object.getLong("memDiscountId"));
            if (highDiscountUserRel == null || highDiscountUserRel.getStatus() != 1) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "优惠券状态错误");
            }
            if (!highDiscountUserRel.getHighDiscount().getUseScope().equals(DiscountUseScope.type1.getType())
                    && !highDiscountUserRel.getHighDiscount().getUseScope().equals(DiscountUseScope.type3.getType())) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "无法使用此优惠券");
            }
        } else {
            outRechargeOrder.setPayRealPrice(outRechargePrice.getPayPrice());
        }

        // 优惠券抵扣
        if (highDiscountUserRel != null) {

            outRechargeOrder.setMemDiscountName(highDiscountUserRel.getHighDiscount().getDiscountName());
            BigDecimal payPrice = new BigDecimal(0);

            // 卡卷类型  1：满减  2：抵扣   3：折扣
            if (highDiscountUserRel.getHighDiscount().getDiscountType() == 1) {
                // 如果商品支付总额 小于 满减价格
                if (outRechargePrice.getRechargePrice().compareTo(highDiscountUserRel.getHighDiscount().getDiscountCondition()) < 0) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.UN_MEMBER_ERROR, "订单未达到" + highDiscountUserRel.getHighDiscount().getDiscountCondition() + "元,无法使用此优惠券");
                }
                // 计算支付金额 = 商品充值总额 - 满减额度
                payPrice = outRechargePrice.getRechargePrice().subtract(highDiscountUserRel.getHighDiscount().getDiscountPrice());
                outRechargeOrder.setDiscountDeductionPrice(highDiscountUserRel.getHighDiscount().getDiscountPrice());

            }

            // 卡卷类型  1：满减  2：抵扣   3：折扣
            if (highDiscountUserRel.getHighDiscount().getDiscountType() == 2) {
                // 计算支付金额 = 商品充值总额 - 满减额度
                payPrice = outRechargePrice.getRechargePrice().subtract(highDiscountUserRel.getHighDiscount().getDiscountPrice());
                outRechargeOrder.setDiscountDeductionPrice(highDiscountUserRel.getHighDiscount().getDiscountPrice());

            }

            // 卡卷类型  1：满减  2：抵扣   3：折扣
            if (highDiscountUserRel.getHighDiscount().getDiscountType() == 3) {
                BigDecimal discountPrice = highDiscountUserRel.getHighDiscount().getDiscountPrice();
                // 订单总额 * 折扣
                payPrice = outRechargePrice.getRechargePrice().multiply(discountPrice);
                outRechargeOrder.setDiscountDeductionPrice(outRechargePrice.getRechargePrice().subtract(payPrice));
                outRechargeOrder.setPayRealPrice(payPrice);
            }

            // 如果总额小于0
            if (payPrice.compareTo(new BigDecimal("0")) < 0) {
                outRechargeOrder.setPayRealPrice(new BigDecimal("0"));
            } else {
                outRechargeOrder.setPayRealPrice(payPrice);
            }
        }

        // 判断积分数量是否大于0
        if (object.getLong("integralNum") > 0 && bsProductDiscount.getDiscount().compareTo(new BigDecimal("0")) > 0) {

            // 判断用户积分是否够
            if (object.getLong("integralNum") > user.getGold()) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "用户积分不足");
            }

            // 积分抵扣金额
            BigDecimal integralDeductionPrice = object.getBigDecimal("integralNum").divide(new BigDecimal(100).setScale(2, RoundingMode.HALF_UP));
            // 最高可抵扣金额
            BigDecimal maxIntegralDeductionPrice = outRechargeOrder.getPayRealPrice().multiply(bsProductDiscount.getDiscount()).divide(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP);
            // 判读积分是否大于限制额度
            if (maxIntegralDeductionPrice.compareTo(integralDeductionPrice) < 0) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "订单最大抵扣积分金额：" + maxIntegralDeductionPrice);
            }

            // 判断积分抵扣比例是否为100% 并且积分数量是否可以抵扣最后的支付金额
            if (bsProductDiscount.getDiscount().compareTo(new BigDecimal(100)) == 0 && integralDeductionPrice.compareTo(outRechargeOrder.getPayRealPrice()) == 0) {
                // 查询用户支付密码
                HighUserPayPassword userPayPassword = highUserPayPasswordService.getDetailByUser(object.getLong("userId"));
                if (userPayPassword == null) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.NOT_SET_USER_PAY_PWD, "");
                }
                if (StringUtils.isBlank(object.getString("password"))) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.NOT_ENTER_USER_PAY_PWD, "");
                }
                // 校验支付密码
                if (!AESEncodeUtil.aesEncrypt(object.getString("password")).equals(userPayPassword.getPassword())) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.USER_PAY_PWD_ERROR, "");
                }
            }

            outRechargeOrder.setIntegralDeductionPrice(integralDeductionPrice);
            outRechargeOrder.setPayRealPrice(outRechargeOrder.getPayRealPrice().subtract(outRechargeOrder.getIntegralDeductionPrice()));

        }

        outRechargeOrder.setUserId(user.getId());
        outRechargeOrder.setIntegralNum(object.getBigDecimal("integralNum"));
        outRechargeOrder.setRechargeContent(rechargeContent);
        outRechargeOrder.setCompanyId(outRechargePrice.getCompanyId());
        outRechargeOrder.setUserName(user.getName());
        outRechargeOrder.setRechargeType(outRechargePrice.getRechargeType());
        outRechargeOrder.setUserPhone(user.getPhone());
        outRechargeOrder.setOrderNo("RCG" + DateUtil.date2String(new Date(), "yyyyMMddHHmmss") + IDGenerator.nextId(5));
        outRechargeOrder.setCreateTimed(new Date());
        outRechargeOrder.setGoodsId(goodsId);
        outRechargeOrder.setMerchId(object.getString("mchId"));
        outRechargeOrder.setRechargePrice(outRechargePrice.getRechargePrice());
        if (object.getLong("memDiscountId") != null) {
            outRechargeOrder.setPayPrice(outRechargePrice.getRechargePrice());
        } else {
            outRechargeOrder.setPayPrice(outRechargePrice.getPayPrice());
        }
        outRechargeOrder.setType(1);
        outRechargeOrder.setOrderPrice(outRechargePrice.getRechargePrice());
        outRechargeOrder.setOperatorName(OperatorEnum.getNameByType(outRechargePrice.getOperatorType()));
        outRechargeOrder.setOperatorType(outRechargePrice.getOperatorType());


        // 判断积分支付是否扣完金额
        if (outRechargeOrder.getPayRealPrice().compareTo(new BigDecimal(0)) == 0) {
            // 201:充值中 202：充值成功 203：充值失败 204：未充值
            outRechargeOrder.setRechargeStatus(204);
            // 101.待支付 102.已支付 100.已完成 104.已取消 105.已退款
            outRechargeOrder.setPayStatus(102);
            outRechargeOrder.setPayTime(new Date());
            outRechargeOrder.setPaySerialNo("22" + DateUtil.date2String(new Date(), "yyyyMMddHHmmss") + IDGenerator.nextId(5));
        } else {
            // 201:充值中 202：充值成功 203：充值失败 204：未充值
            outRechargeOrder.setRechargeStatus(204);
            // 101.待支付 102.已支付 100.已完成 104.已取消 105.已退款
            outRechargeOrder.setPayStatus(101);
        }

        // 使用优惠券
        if (outRechargeOrder.getMemDiscountId() != null) {
            HighDiscountUserRel discountUserRel = highDiscountUserRelService.getRelById(outRechargeOrder.getMemDiscountId());
            discountUserRel.setUseTime(new Date()); // 使用时间
            discountUserRel.setStatus(2);  //状态  0:已过期  1：未使用  2：已使用
            highDiscountUserRelService.updateDiscountUserRel(discountUserRel);

            HighDiscountAgentCode code = highDiscountAgentCodeService.getCodeById(discountUserRel.getDiscountAgentCodeId());
            code.setStatus(3);
            highDiscountAgentCodeService.updateCode(code);
        }



        outRechargeOrderMapper.insert(outRechargeOrder);

        if (outRechargeOrder.getIntegralNum() != null) {
            String remark = "话费订单" + outRechargeOrder.getOrderNo() + "下单，使用积分：" +  object.getInteger("integralNum");
            highUserService.goldHandle(outRechargeOrder.getUserId(), outRechargeOrder.getIntegralNum().intValue(), 2, 2, outRechargeOrder.getId() , remark);
        }

        if (outRechargeOrder.getPayStatus() == 102) {
            pollRequest(outRechargeOrder);
        }

        return outRechargeOrder;

    }

    @Override
    public void updateOrder(OutRechargeOrder outRechargeOrder) {
        outRechargeOrderMapper.updateByPrimaryKey(outRechargeOrder);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateOrderList(List<OutRechargeOrder> rechargeOrders) throws Exception {
        for (OutRechargeOrder list : rechargeOrders) {
//            if (list.getStatus() == 3) {
//                outRechargeOrderMapper.updateByPrimaryKey(list);
//            } else if (list.getStatus() == 6) {
//                rechargeOrderToRefund(list.getId());
//            }

        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void cancelOrder(Long orderId) {
        OutRechargeOrder order = findByOrderId(orderId);
        if (order != null && order.getPayStatus() == 101) {
            // 101.待支付 102.已支付 100.已完成 104.已取消 105.已退款
            order.setPayStatus(104);
            order.setCancelTime(new Date());

            if (order.getMemDiscountId() != null) {
                HighDiscountUserRel rel = highDiscountUserRelService.getRelById(order.getMemDiscountId());
                if (rel != null) {
                    rel.setStatus(1);  // 状态  0:已过期  1：未使用  2：已使用
                    rel.setUseTime(null);
                    highDiscountUserRelService.updateDiscountUserRel(rel);

                    HighDiscountAgentCode code = highDiscountAgentCodeService.getCodeById(rel.getDiscountAgentCodeId());
                    code.setStatus(2);
                    highDiscountAgentCodeService.updateCode(code);
                }
            }

            if (order.getIntegralNum() != null) {
                // 积分返回
                String remark = "话费订单" + order.getOrderNo() + "取消，退还积分：" +  order.getIntegralNum().intValue();
                highUserService.goldHandle(order.getUserId(), order.getIntegralNum().intValue(), 1, 3, order.getId() , remark);
            }

            updateOrder(order);
        }

    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void finishOrder(Long orderId) {
        OutRechargeOrder order = findByOrderId(orderId);
        if (order != null) {

            new Thread(() -> {
                JSONObject object = new JSONObject();

                object.put("type" , 3);
                object.put("productId" , order.getOperatorType());
                object.put("companyId" , order.getCompanyId());
                object.put("price" , order.getPayRealPrice());
                object.put("userId" , order.getUserId());
                object.put("orderId" , order.getId());
                object.put("remark" , "话费订单" + order.getOrderNo() + "积分返利：");


                Map<String, Object> map = new HashMap<>();
                map.put("goldType", 1);
                map.put("resType", 4);
                map.put("userId", order.getUserId());
                map.put("resId", order.getId());

                List<HighGoldRec> goldRecs = highGoldRecService.getGoldRec(map);

                if (goldRecs.size() == 0) {
                    bsIntegralRebateService.integralRebate(object);
                }

            }).start();

            order.setRechargeStatus(202); // 订单状态：1 待支付  2 已支付  3.已完成  4. 已取消  5.已退款
            order.setPayStatus(100); // 订单状态：1 待支付  2 已支付  3.已完成  4. 已取消  5.已退款
            order.setFinishTime(new Date());
            updateOrder(order);
        }
    }

    @Override
    public List<OutRechargeOrderModel> getOrderCount(Map<String, Object> map) throws Exception {


        if (MapUtils.getLong(map, "createTimeS") != null) {
            map.put("createTimeS", MapUtils.getString(map, "createTimeS"));
        }

        if (MapUtils.getLong(map, "createTimeE") != null) {
            map.put("createTimeE", MapUtils.getString(map, "createTimeE"));
        }

        if (MapUtils.getLong(map, "payTimeS") != null) {
            map.put("payTimeS", MapUtils.getString(map, "payTimeS"));
        }

        if (MapUtils.getLong(map, "payTimeE") != null) {
            map.put("payTimeE", MapUtils.getString(map, "payTimeE"));
        }

        return outRechargeOrderMapper.selectOrderCount(map);
    }

    @Override
    public Long CountOrder() {
        OutRechargeOrderExample example = new OutRechargeOrderExample();
//        example.createCriteria().andStatusEqualTo(2);
        return outRechargeOrderMapper.countByExample(example);
    }

    @Override
    public List<OutOrderModel> getListOrderCount(Map<String, String> map) throws Exception {
        String finishTimeS = map.get("finishTimeS");
        String finishTimeE = map.get("finishTimeE");
        Integer status;
        if (StringUtils.isNotBlank(map.get("status"))) {
            status = Integer.valueOf(map.get("status"));
        } else {
            status = null;
        }
        String fTimeS;
        String fTimeE;
        if (StringUtils.isNotBlank(finishTimeS)) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date(Long.parseLong(finishTimeS)));
            //时
            calendar.set(Calendar.HOUR_OF_DAY, 00);
            //分
            calendar.set(Calendar.MINUTE, 00);
            //秒
            calendar.set(Calendar.SECOND, 00);
            fTimeS = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());

        } else {
            fTimeS = "2010-09-13 22:36:01";
        }
        if (StringUtils.isNotBlank(finishTimeE)) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date(Long.parseLong(finishTimeE)));
            //时
            calendar.set(Calendar.HOUR_OF_DAY, 00);
            //分
            calendar.set(Calendar.MINUTE, 00);
            //秒
            calendar.set(Calendar.SECOND, 00);
            fTimeE = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());
        } else {
            fTimeE = DateUtil.date2String(new Date(), "yyyy-MM-dd HH:mm:ss");
        }
        return outRechargeOrderMapperExt.getListOrderCount(fTimeS, fTimeE, status);
    }

    @Override
    public List<OutUserOrderModel> getUserCountList(Map<String, String> map) throws Exception {
        String finishTimeS = map.get("finishTimeS");
        String finishTimeE = map.get("finishTimeE");
        String fTimeS;
        String fTimeE;
        if (StringUtils.isNotBlank(finishTimeS)) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date(Long.parseLong(finishTimeS)));
            //时
            calendar.set(Calendar.HOUR_OF_DAY, 00);
            //分
            calendar.set(Calendar.MINUTE, 00);
            //秒
            calendar.set(Calendar.SECOND, 00);
            fTimeS = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());

        } else {
            fTimeS = "2010-09-13 22:36:01";
        }
        if (StringUtils.isNotBlank(finishTimeE)) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date(Long.parseLong(finishTimeE)));
            //时
            calendar.set(Calendar.HOUR_OF_DAY, 00);
            //分
            calendar.set(Calendar.MINUTE, 00);
            //秒
            calendar.set(Calendar.SECOND, 00);
            fTimeE = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());
        } else {
            fTimeE = DateUtil.date2String(new Date(), "yyyy-MM-dd HH:mm:ss");
        }
        return outRechargeOrderMapperExt.getListUserCount(fTimeS, fTimeE);
    }

    @Override
    public void hltUnionCardPay(HighUserCard userCard, OutRechargeOrder order) throws Exception {

        String goodsDesc = "充值话费";
        String tranDesc = order.getRechargeContent() + "充值" + order.getPayRealPrice() + "元话费";
        String instCode = "11101527";
        String businessType = "hisen_consume";

        // 工会卡支付
        JSONObject consumption = HuiLianTongUnionCardConfig.consumption(order.getOrderNo(), userCard.getCardNo(), order.getPayRealPrice(), businessType, instCode, goodsDesc, tranDesc);
        System.out.println("工会卡支付响应参数" + consumption.toJSONString());

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("orderNo", order.getOrderNo());
        dataMap.put("cardType", "ghk");
        dataMap.put("cardNo", userCard.getCardNo());
        dataMap.put("checkPassword", "N");
        dataMap.put("tranAmount", order.getPayRealPrice());
        dataMap.put("tranChannel", "HiSen");
        dataMap.put("businessType", businessType);
        dataMap.put("instCode", instCode);
        dataMap.put("goodsDesc", goodsDesc);
        dataMap.put("tranDesc", tranDesc);
        HighGasOrderPush payPush = new HighGasOrderPush();
        payPush.setType(OrderPushType.type5.getType());
        payPush.setOrderNo(order.getOrderNo());
        payPush.setCreateTime(new Date());
        payPush.setCode(consumption.getString("respCode"));
        payPush.setRequestContent(JSON.toJSONString(dataMap));
        payPush.setReturnContent(consumption.toJSONString());
        highGasOrderPushMapper.insert(payPush);

        if (!consumption.getString("respCode").equals("0000")) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, consumption.getString("respMessage"));
        }
        JSONObject consumptionResult = HuiLianTongUnionCardConfig.resolveResponse(consumption.getString("data"));
        if (!consumptionResult.getBoolean("success")) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, consumptionResult.getString("message"));
        }
        order.setPaySerialNo(consumptionResult.getString("orderId")); // 支付流水号
        order.setPayRealPrice(order.getPayRealPrice()); // 实付金额
        order.setPayStatus(102);
        order.setRechargeStatus(204);
        order.setLaborUnionCard(userCard.getCardNo());
        order.setPayType(3);
        order.setPayTime(new Date()); // 支付时间
        updateOrder(order);
        outRechargeOrderService.pollRequest(order);

    }

    @Override
    public List<OutRechargeOrder> getOutRechargeOrderList() {
        return outRechargeOrderMapper.getCloseOrder();
    }

    @Override
    public OrderCountModel rechargeOrderByIndex(Integer code) {
        return outRechargeOrderMapper.rechargeOrderByIndex(code);
    }


    @Override
    public void rechargeOrderToRefund(Long orderId) throws Exception {
        OutRechargeOrder order = outRechargeOrderService.findByOrderId(orderId);

        // 101.待支付 102.已支付 100.已完成 104.已取消 105.已退款
        if (order.getPayStatus() != 102) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "无法退款，订单不处于已支付状态");
        }

        //  充值状态：201:充值中 202：充值成功 203：充值失败 204:未充值
        if (order.getRechargeStatus() == 201) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "无法退款，订单处于充值中状态");
        }

        // 微信退款
        if (order.getPayType() == 2) {
            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.setPayStatus(105);
                order.setRechargeStatus(203);
                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);
            } else {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "退款失败！错误代码：" + orderRefundModel.getErr_code() + ",错误描述" + orderRefundModel.getErr_code_des());
            }
        }

        // 工会卡退款
        if (order.getPayType() == 3) {
            JSONObject jsonObject = HuiLianTongUnionCardConfig.refund("HFR" + new Date().getTime(), order.getOrderNo());

            if (jsonObject == null) {
                jsonObject = HuiLianTongUnionCardConfig.refund("HFR" + new Date().getTime(), order.getOrderNo());
            }

            JSONObject dataObject = HuiLianTongUnionCardConfig.resolveResponse(jsonObject.getString("data"));

            if (dataObject.getBoolean("success") || Objects.equals(dataObject.getString("message"), "原交易已撤销,不可再次操作")) {
                order.setPayStatus(105);
                order.setRechargeStatus(203);
                order.setRefundTime(new Date());
                order.setOutRefundNo("HFR" + new Date().getTime());
                order.setRefundFee(order.getPayRealPrice());
                order.setRefundId(dataObject.getString("orderId"));
                outRechargeOrderService.updateOrder(order);

            } else {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, dataObject.getString("message"));
            }

            // 商户预充值 帐户退款
            if (order.getPayType() == 6) {

                Map<String , Object> map = new HashMap<>();
                map.put("orderNo" , order.getOrderNo());
                map.put("amountType" , 1);
                map.put("sourceType" , 2);

                if ( apiAmountRecordService.getApiAmountRecordByList(map).size() == 1) {

                    ApiMerchants apiMerchants = apiMerchantsService.findByMchId(order.getMerchId());
                    // 插入金额记录
                    // 变更前金额
                    BigDecimal beforeAmount = apiMerchants.getAmounts();
                    // 计算金额
                    apiMerchants.setAmounts(apiMerchants.getAmounts().add(order.getPayPrice()));
                    // 变更后金额
                    BigDecimal afterAmount = apiMerchants.getAmounts();

                    apiMerchantsService.updateApiMerchants(apiMerchants);

                    ApiAmountRecord apiAmountRecord = new ApiAmountRecord();

                    apiAmountRecord.setCreateTime(new Date());
                    apiAmountRecord.setUpdateTime(new Date());
                    apiAmountRecord.setMchId(order.getMerchId());

                    apiAmountRecord.setStatus(100);
                    apiAmountRecord.setAmount(order.getPayPrice());
                    apiAmountRecord.setAfterAmount(afterAmount);
                    apiAmountRecord.setBeforeAmount(beforeAmount);
                    apiAmountRecord.setAmountType(1);
                    apiAmountRecord.setSourceType(2);
                    apiAmountRecord.setSourceOrderNo(order.getOrderNo());
                    apiAmountRecord.setSourceId(order.getId());
                    apiAmountRecord.setSourceContent(apiMerchants.getMerchantName() + "|订单退款"  + order.getPayPrice());

                    apiAmountRecordService.insertAmountRecord(apiAmountRecord);

                    Map<String, Object> orderMap = new HashMap<>();
                    orderMap.put("orderId" , order.getId());

                    // 查询是否用重复订单
                    ApiOrderRecord apiOrderRecord = apiOrderRecordService.queryOrderResult(orderMap);

                    apiOrderRecord.setStatus(100);
                    apiOrderRecord.setRequestTime(new Date());
                    apiOrderRecordService.updateOrderRecord(apiOrderRecord);
                }

            }
        }

        // 银联退款
        if (order.getPayType() == 4) {
            // 订单退款
            JSONObject refund = UnionPayConfig.zwrefund(UnionPayConfig.MER_ID2, UnionPayConfig.TERM_ID2, 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.setPayStatus(105);
            order.setRechargeStatus(203);
            order.setRefundTime(new Date());
            order.setOutRefundNo(refund.getString("oriwtorderid"));
            order.setRefundFee(order.getPayRealPrice());
            outRechargeOrderService.updateOrder(order);
        }


        if (order.getMemDiscountId() != null) {
            HighDiscountUserRel rel = highDiscountUserRelService.getRelById(order.getMemDiscountId());
            if (rel != null) {
                rel.setStatus(1);  // 状态  0:已过期  1：未使用  2：已使用
                rel.setUseTime(null);
                highDiscountUserRelService.updateDiscountUserRel(rel);

                HighDiscountAgentCode code = highDiscountAgentCodeService.getCodeById(rel.getDiscountAgentCodeId());
                code.setStatus(2);
                highDiscountAgentCodeService.updateCode(code);
            }
        }


        // 退还积分
        if (order.getIntegralNum().compareTo(new BigDecimal(0)) > 0) {
            String remark = "话费订单" + order.getOrderNo() + "退款，退还积分：" +  order.getIntegralNum().intValue();
            highUserService.goldHandle(order.getUserId(), order.getIntegralNum().intValue(), 1, 3, order.getId() , remark);
            if (order.getPayRealPrice().compareTo(new BigDecimal(0)) == 0) {
                order.setPayStatus(105);
                order.setRechargeStatus(203);
                order.setRefundTime(new Date());
                outRechargeOrderService.updateOrder(order);
            }
        }

    }

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

    @Override
    public void pollRequest(OutRechargeOrder outRechargeOrder) throws Exception {

        // 查询充值产品
        OutRechargePriceModel outRechargePrice = outRechargePriceService.findById(outRechargeOrder.getGoodsId(), null);
        // 查询充值子订单
        Map<String, Object> childOrderMap = new HashMap<>();

        // 添加查询是否存在充值中的子订单
        childOrderMap.put("parent_order_id", outRechargeOrder.getId());
        childOrderMap.put("status", 102);
        List<OutRechargeChildOrder> childOrderList = outRechargeChildOrderService.getListRechargeChildOrder(childOrderMap);

        // 定义新的子订单对象
        OutRechargeChildOrder childOrder = new OutRechargeChildOrder();

        // 1:尖椒 2：龙阅 3：畅停
        int type = 0;
        // 定义新增子订单充值平台
        int rechargePlatformType = 0;

        // 判断子订单是否存在充值中订单
        if (childOrderList.size() > 0) {
            childOrder = childOrderList.get(0);
            childOrder.setStatus(103);
            childOrder.setUpdateTime(new Date());
            outRechargeChildOrderService.updateOrder(childOrder);
            type = childOrder.getRechargePlatform();

        } else {
            // 查询充值状态为103充值失败的子订单
            Map<String, Object> childOrderMap103 = new HashMap<>();

            childOrderMap103.put("parent_order_id", outRechargeOrder.getId());
            childOrderMap103.put("status", 103);

            List<OutRechargeChildOrder> childOrderList103 = outRechargeChildOrderService.getListRechargeChildOrder(childOrderMap103);
            if (childOrderList103.size() > 0) {
                type = childOrderList103.get(0).getRechargePlatform();
            }
        }

        if (type == 3) {
            type = 1;
        } else {
            type++;
        }

        JSONObject object = new JSONObject();

        // 定义订单哈
        String orderNo = "CZ" + DateUtil.date2String(new Date(), "yyyyMMddHHmmss") + IDGenerator.nextId(5);

        // 查询平台
        String string = outRechargePrice.getRechargePlatform().substring(1,outRechargePrice.getRechargePlatform().length()-1);
        String[] rechargePlatform = string.split("-");

        // 判断平台只定义一个那么类型就是唯一
        if (string.length() == 1) {
            type = Integer.parseInt(string);
        }

        // 定义查询充值产品编码
        Map<String, Object> map = new HashMap<>();
        map.put("type" , 1);

        for (String s : rechargePlatform) {
            // 尖椒充值
            System.out.println("话费定时任务 -> 需要重新充值：尖椒开始");
            if (s.equals("1") && type == 1) {
                object.put("out_order_id", orderNo);
                object.put("amount", outRechargePrice.getRechargePrice());
                object.put("mobile", outRechargeOrder.getRechargeContent());
                object.put("notifyUrl", CommonSysConst.getSysConfig().getJjNotifyUrl());
                JSONObject returnObject = RechargeConfig.rechargeOrderByJj(object);
                object.put("return_content", returnObject);
                if (returnObject != null && returnObject.getLong("code") == 200) {
                    childOrder.setStatus(102);
                } else {
                    childOrder.setStatus(103);
                }
                rechargePlatformType = 1;
                break;
            }
            // 龙阅充值
            if (s.equals("2") && type == 2) {

                map.put("sourceId" , outRechargePrice.getId());
                map.put("rechargePlatform" , type);
                BsRechargeCode rechargeCode = rechargeCodeService.findByMap(map);
                System.out.println("话费定时任务 -> 需要重新充值：龙阅开始");
                object.put("out_trade_num", orderNo);
                object.put("product_id", rechargeCode.getGoodsId());
                object.put("mobile", outRechargeOrder.getRechargeContent());
                object.put("notifyUrl", CommonSysConst.getSysConfig().getLyNotifyUrl());
                JSONObject returnObject = RechargeConfig.rechargeOrderByLy(object);
                object.put("return_content", returnObject);
                if (returnObject != null && returnObject.getLong("errno") == 0) {
                    childOrder.setStatus(102);
                } else {
                    childOrder.setStatus(103);
                }
                rechargePlatformType = 2;
                break;
            }
            // 城宇充值
            if (s.equals("3") && type == 3) {

                map.put("sourceId" , outRechargePrice.getId());
                map.put("rechargePlatform" , type);
                BsRechargeCode rechargeCode = rechargeCodeService.findByMap(map);

                System.out.println("话费定时任务 -> 需要重新充值：龙阅开始");
                object.put("agentOrderId", orderNo);
                object.put("productId", rechargeCode.getGoodsId());
                object.put("mobile", outRechargeOrder.getRechargeContent());
                JSONObject returnObject = RechargeConfig.rechargeOrderByCy(object);
                object.put("return_content", returnObject);
                if (returnObject != null && returnObject.getBoolean("success")) {
                    childOrder.setStatus(102);
                } else {
                    childOrder.setStatus(103);
                }
                rechargePlatformType = 3;
                break;
            }
        }

        childOrder.setOrderNo(orderNo);
        childOrder.setCreateTime(new Date());
        childOrder.setParentOrderId(outRechargeOrder.getId());
        childOrder.setRechargePlatform(rechargePlatformType);
        childOrder.setUpdateTime(new Date());
        outRechargeChildOrderService.insertOrder(childOrder);

        // 创建提交记录
        BsRequestRecord requestRecord = new BsRequestRecord();
        requestRecord.setCreateTime(new Date());
        requestRecord.setUpdateTime(new Date());
        requestRecord.setOrderNo(orderNo);
        requestRecord.setRequestContent(object.toJSONString());
        requestRecord.setOperatorId(0L);
        requestRecord.setOperatorName("系统生成");
        requestRecord.setSourceId(childOrder.getId().toString());
        requestRecord.setSourceType(1);

        bsRequestRecordService.insertRequestRecord(requestRecord);

        // 判断是否充值提交成功
        if (childOrder.getStatus() == 102) {
            outRechargeOrder.setRechargeStatus(201);
        }

        if (childOrder.getStatus() == 103) {
            outRechargeOrder.setRechargeStatus(204);
        }
        outRechargeOrderService.updateOrder(outRechargeOrder);
        System.out.println("话费定时任务 -> 需要重新充值：结束");
    }

    @Override
    public Integer rechargeOrderNum(Long userId) {
        OutRechargeOrderExample example = new OutRechargeOrderExample();
        OutRechargeOrderExample.Criteria criteria = example.createCriteria();

        criteria.andUserIdEqualTo(userId);
        criteria.andPayStatusEqualTo(101);
        return outRechargeOrderMapper.selectByExample(example).size();
    }

}
