package com.xhpc.activity.service.impl;

import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;
import com.xhpc.activity.config.AliOSSProperties;
import com.xhpc.activity.domain.XhpcClearingBankDomain;
import com.xhpc.activity.domain.XhpcClearingCheckoutDomain;
import com.xhpc.activity.domain.XhpcClearingHistoryOrderDomain;
import com.xhpc.activity.domain.XhpcClearingReceiptDomain;
import com.xhpc.activity.mapper.XhpcClearingBankMapper;
import com.xhpc.activity.mapper.XhpcClearingCheckoutMapper;
import com.xhpc.activity.mapper.XhpcClearingHistoryOrderMapper;
import com.xhpc.activity.mapper.XhpcClearingReceiptMapper;
import com.xhpc.activity.service.XhpcClearingCheckoutService;
import com.xhpc.activity.task.AsyncService;
import com.xhpc.activity.utils.DownloadUtil;
import com.xhpc.activity.vo.CheckoutBankVo;
import com.xhpc.activity.vo.ClearingReceiptVo;
import com.xhpc.common.core.domain.R;
import com.xhpc.common.core.exception.CustomException;
import com.xhpc.common.core.utils.SecurityUtils;
import com.xhpc.common.core.utils.StringUtils;
import com.xhpc.common.core.web.service.BaseService;
import com.xhpc.common.redis.service.RedisService;
import com.xhpc.common.security.service.TokenService;
import com.xhpc.common.util.UserTypeUtil;
import com.xhpc.system.api.domain.SysUser;
import com.xhpc.system.api.model.LoginUser;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Service
@Transactional
public class XhpcClearingCheckoutServiceImpl extends BaseService implements XhpcClearingCheckoutService {


    @Resource
    XhpcClearingCheckoutMapper checkoutMapper;

    @Resource
    XhpcClearingHistoryOrderMapper historyOrderMapper;

    @Resource
    XhpcClearingBankMapper bankMapper;

    @Resource
    XhpcClearingReceiptMapper receiptMapper;

    @Resource
    RedisService redisService;

    @Resource
    AliOSSProperties ossProperties;

    @Resource
    TokenService tokenService;

    @Resource
    AsyncService asyncService;

    private final ExecutorService executorService = Executors.newFixedThreadPool(20);

    @Override
    public List<XhpcClearingCheckoutDomain> getPage(Map<String, Object> params) {

        LoginUser loginUser = tokenService.getLoginUser();
        SysUser sysUser = loginUser.getSysUser();
        Long sysUserId = sysUser.getUserId();
        if(!UserTypeUtil.SYS_USER_TYPE_ADMIN.equals(sysUser.getUserId())){

            if(UserTypeUtil.SYS_USER_TYPE_ONE.equals(sysUser.getUserType())){
                Long logOperatorId = sysUser.getOperatorId();
                //运营商看自己的场站
                params.put("type", 1);
                params.put("logOperatorId",logOperatorId);
                return checkoutMapper.selectByParams(params);
            }else{
                //查询赋值的场站
                params.put("type", 2);
                params.put("logOperatorId",sysUserId);
                return checkoutMapper.selectByParams(params);
            }
        }else{
            params.put("type", 0);
            params.put("logOperatorId",sysUserId);
            params.put("tenantId", "");
            return checkoutMapper.selectByParams(params);
        }
    }
    @Override
    public List<Map<String, Object>> getCheckoutPage(Map<String, Object> params){

        //获取运营商
        List<Map<String, Object>> mapList = checkoutMapper.getXhpcOperatorParams(params);
        BigDecimal bankRate = new BigDecimal("0.006");
        BigDecimal handlingAmount = BigDecimal.TEN;

        if (mapList != null && !mapList.isEmpty()) {
            // 提取所有运营商ID
            List<String> operatorIds = mapList.stream()
                    .map(map -> map.get("operatorId").toString())
                    .collect(Collectors.toList());

            // 1. 批量获取待清分金额
            List<Map<String, Object>> unClearingAmountList = checkoutMapper.selectUnclearingAmountBatch(operatorIds, params);
            Map<String, BigDecimal> unClearingAmountMap = unClearingAmountList.stream()
                    .collect(Collectors.toMap(
                            m -> m.get("operatorId").toString(),
                            m -> new BigDecimal(m.get("unClearingAmount").toString())
                    ));

            // 2. 批量获取已提现和提现中金额
            List<Map<String, Object>> cashAmountList = checkoutMapper.selectCashedAmountOrCashingAmountBatch(operatorIds);
            Map<String, Map<String, BigDecimal>> cashAmountMap = cashAmountList.stream()
                    .collect(Collectors.toMap(
                            m -> m.get("operatorId").toString(),
                            m -> {
                                Map<String, BigDecimal> map = new HashMap<>();
                                map.put("cashingAmount", new BigDecimal(m.get("cashingAmount").toString()));
                                map.put("cashedAmount", new BigDecimal(m.get("cashedAmount").toString()));
                                return map;
                            }
                    ));

            // 3. 批量获取不参与清分金额相关数据
            List<Map<String, Object>> excludeClearingList = checkoutMapper.selectCashAmountYuBatch(operatorIds);
            Map<String, Map<String, BigDecimal>> excludeClearingMap = excludeClearingList.stream()
                    .collect(Collectors.toMap(
                            m -> m.get("operatorId").toString(),
                            m -> {
                                Map<String, BigDecimal> map = new HashMap<>();
                                map.put("powerAmount", new BigDecimal(m.get("powerAmount").toString()));
                                map.put("serviceAmount", new BigDecimal(m.get("serviceAmount").toString()));
                                return map;
                            }
                    ));

            // 4. 批量获取清分清分价格和总金额
            List<Map<String, Object>> clearingPriceList = checkoutMapper.selectClearingPriceBatch(operatorIds, params);
            Map<String, Map<String, BigDecimal>> clearingPriceMap = clearingPriceList.stream()
                    .collect(Collectors.toMap(
                            m -> m.get("operatorId").toString(),
                            m -> {
                                Map<String, BigDecimal> map = new HashMap<>();
                                map.put("clearingPrice", new BigDecimal(m.get("clearingPrice").toString()));
                                map.put("actTotalPrice", new BigDecimal(m.get("actTotalPrice").toString()));
                                return map;
                            }
                    ));

            // 组装数据
            for (Map<String, Object> map : mapList) {
                String operatorId = map.get("operatorId").toString();

                // 待清分金额
                BigDecimal unClearingAmount = unClearingAmountMap.getOrDefault(operatorId, BigDecimal.ZERO);
                map.put("unClearingAmount", unClearingAmount.compareTo(BigDecimal.ZERO) >= 0 ? unClearingAmount : BigDecimal.ZERO);

                // 已提现金额和提现中金额
                Map<String, BigDecimal> cashMap = cashAmountMap.getOrDefault(operatorId, new HashMap<>());
                map.putAll(cashMap);

                // 不参与清分金额数据
                Map<String, BigDecimal> excludeMap = excludeClearingMap.getOrDefault(operatorId, new HashMap<>());
                BigDecimal powerAmountYu = excludeMap.getOrDefault("powerAmount", BigDecimal.ZERO).setScale(2, BigDecimal.ROUND_HALF_UP);
                BigDecimal serviceAmountYu = excludeMap.getOrDefault("serviceAmount", BigDecimal.ZERO).setScale(2, BigDecimal.ROUND_HALF_UP);
                BigDecimal bankFeeYu = powerAmountYu.add(serviceAmountYu).multiply(bankRate).setScale(2, BigDecimal.ROUND_HALF_UP);
                BigDecimal receivedServiceAmountYu = serviceAmountYu.subtract(handlingAmount).subtract(bankFeeYu);

                // 可提现金额
                BigDecimal cashableAmount = powerAmountYu.add(receivedServiceAmountYu);
                map.put("cashAmount", cashableAmount.compareTo(BigDecimal.ZERO) >= 0 ? cashableAmount : BigDecimal.ZERO);

                // 清分价格和总金额
                Map<String, BigDecimal> clearingMap = clearingPriceMap.getOrDefault(operatorId, new HashMap<>());
                BigDecimal clearingPrice = clearingMap.getOrDefault("clearingPrice", BigDecimal.ZERO);
                BigDecimal actTotalPrice = clearingMap.getOrDefault("actTotalPrice", BigDecimal.ZERO);

                map.put("clearingPrice", clearingPrice.compareTo(BigDecimal.ZERO) >= 0 ? clearingPrice : BigDecimal.ZERO);
                map.put("actTotalPrice", actTotalPrice.compareTo(BigDecimal.ZERO) >= 0 ? actTotalPrice : BigDecimal.ZERO);
                map.put("bankFeeYu", bankFeeYu.compareTo(BigDecimal.ZERO) >= 0 ? bankFeeYu : BigDecimal.ZERO);
                map.put("handlingAmount", handlingAmount);
            }
        }
        return mapList;
    }


    public List<Map<String, Object>> getCheckoutPageYu(Map<String, Object> params){

        //获取运营商
        List<Map<String, Object>> mapList = checkoutMapper.getXhpcOperatorParams(params);
        BigDecimal bankRate = new BigDecimal("0.006");
        BigDecimal handlingAmount = BigDecimal.TEN;
        if(mapList !=null && mapList.size()>0){
            // 可提现金额
            for (int i = 0; i <mapList.size() ; i++) {
                Map<String, Object> map = mapList.get(i);
                //统计带清分金额、可提现金额、提现中金额、已提现金额、不参与清分金额
                String operatorId = map.get("operatorId").toString();
                params.put("operatorId",operatorId);
                // 待清分金额
                BigDecimal unClearingAmount = checkoutMapper.selectUnclearingAmount(params);
                map.put("unClearingAmount",unClearingAmount.compareTo(BigDecimal.ZERO)>=0?unClearingAmount:BigDecimal.ZERO);
                // 已提现金额\提现中金额
                map.putAll(checkoutMapper.selectCashedAmountOrCashingAmount(operatorId));


                //剔除不参与清分金额
                Map<String, Object> cashMapYu = historyOrderMapper.selectCashAmountYu(operatorId);
                BigDecimal powerAmountYu = new BigDecimal(cashMapYu.get("powerAmount").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
                BigDecimal serviceAmountYu =  new BigDecimal(cashMapYu.get("serviceAmount").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
                BigDecimal bankFeeYu = powerAmountYu.add(serviceAmountYu).multiply(bankRate).setScale(2, BigDecimal.ROUND_HALF_UP);
                BigDecimal receivedServiceAmountYu = serviceAmountYu.subtract(handlingAmount).subtract(bankFeeYu);
                //可提现金额
                map.put("cashAmount", powerAmountYu.add(receivedServiceAmountYu).compareTo(BigDecimal.ZERO) >= 0 ? powerAmountYu.add(receivedServiceAmountYu) : BigDecimal.ZERO);
                Map<String, Object> cashMap= checkoutMapper.selectClearingPrice(params);
                BigDecimal clearingPrice =new BigDecimal(cashMap.get("clearingPrice").toString());
                BigDecimal actTotalPrice =new BigDecimal(cashMap.get("actTotalPrice").toString());
                // 不参与清分金额
                map.put("clearingPrice",clearingPrice.compareTo(BigDecimal.ZERO)>=0?clearingPrice:BigDecimal.ZERO);
                //清分总金额
                map.put("actTotalPrice",actTotalPrice.compareTo(BigDecimal.ZERO)>=0?actTotalPrice:BigDecimal.ZERO);
                //微信/支付宝手续费
                map.put("bankFeeYu",bankFeeYu.compareTo(BigDecimal.ZERO)>=0?bankFeeYu:BigDecimal.ZERO);
                //银行提现费用
                map.put("handlingAmount",handlingAmount);

            }
        }

        return mapList;
    }

    @Override
    public R getTmpCheckoutData(Long operatorId) {
        XhpcClearingBankDomain bankDomain = bankMapper.selectOneByOperatorId(operatorId.toString());
        if (bankDomain == null) {
            throw new CustomException("请先输入一个有效的提现账户");
        }

        // 可提现金额
        BigDecimal bankRate = new BigDecimal("0.006");
        BigDecimal handlingAmount = BigDecimal.TEN;
        //全部金额包含不参与清分金额
        Map<String, Object> cashMap = historyOrderMapper.selectCashAmount(operatorId.toString());
        BigDecimal powerAmount = new BigDecimal(cashMap.get("powerAmount").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
        BigDecimal serviceAmount =  new BigDecimal(cashMap.get("serviceAmount").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
        BigDecimal clearingPrice =  new BigDecimal(cashMap.get("clearingPrice").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
        BigDecimal bankFee = powerAmount.add(serviceAmount).multiply(bankRate).setScale(2, BigDecimal.ROUND_HALF_UP);
        BigDecimal receivedServiceAmount = serviceAmount.subtract(handlingAmount).subtract(bankFee);

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("bankNo", bankDomain.getBankNo());
        resultMap.put("contactPhone", bankDomain.getContactPhone());
        resultMap.put("applyAmount", powerAmount.add(serviceAmount));
        resultMap.put("applyPowerAmount", powerAmount);
        resultMap.put("applyServiceAmount", serviceAmount);
        resultMap.put("clearingOrderIds", cashMap.get("clearingOrderIds"));
        resultMap.put("handlingFee", handlingAmount);

        resultMap.put("clearingPrice", clearingPrice);

        //剔除不参与清分金额
        Map<String, Object> cashMapYu = historyOrderMapper.selectCashAmountYu(operatorId.toString());
        BigDecimal powerAmountYu = new BigDecimal(cashMapYu.get("powerAmount").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
        BigDecimal serviceAmountYu =  new BigDecimal(cashMapYu.get("serviceAmount").toString()).setScale(2, BigDecimal.ROUND_HALF_UP);
        BigDecimal bankFeeYu = powerAmountYu.add(serviceAmountYu).multiply(bankRate).setScale(2, BigDecimal.ROUND_HALF_UP);
        BigDecimal receivedServiceAmountYu = serviceAmountYu.subtract(handlingAmount).subtract(bankFeeYu);
        resultMap.put("bankFee", bankFeeYu);
        resultMap.put("clearingPower", powerAmountYu);
        resultMap.put("clearingService", serviceAmountYu);
        resultMap.put("receivedPowerAmount", powerAmountYu);
        resultMap.put("receivedServiceAmount", receivedServiceAmountYu);
        resultMap.put("receivedAmount", powerAmountYu.add(receivedServiceAmountYu).compareTo(BigDecimal.ZERO) >= 0 ? powerAmountYu.add(receivedServiceAmountYu) : BigDecimal.ZERO);
        resultMap.put("clearingBankId", bankDomain.getClearingBankId());
        return R.ok(resultMap);
    }


    @Override
    public XhpcClearingCheckoutDomain getDomainByPk(Long checkoutId) {
        XhpcClearingCheckoutDomain checkoutDomain = checkoutMapper.selectByPrimaryKey(checkoutId);
        checkoutDomain.setClearingBank(bankMapper.selectByPrimaryKey(checkoutDomain.getClearingBankId()));
        return checkoutDomain;
    }


    @Override
    public boolean insertDomain(XhpcClearingCheckoutDomain domain) {

        XhpcClearingBankDomain bankDomain;
        if (domain.getClearingBankId() == null) {
            bankDomain = bankMapper.selectOneByOperatorId(domain.getOperatorId().toString());
            domain.setClearingBankId(bankDomain.getClearingBankId());
        } else {
            bankDomain = bankMapper.selectByPrimaryKey(domain.getClearingBankId());
        }
        //提交申请提现后需要等待10分钟

        String keys = "tixian:" + bankDomain.getContactPhone();
        if(redisService.getCacheObject(keys)==null){
            redisService.setCacheObject(keys, bankDomain.getContactPhone(), 600L, TimeUnit.SECONDS);
        }else{
            throw new CustomException("已申请提现，系统在计算中请等待");
        }

        String key = "opcash:" + bankDomain.getContactPhone();
        String redisCode = redisService.getCacheObject(key);
        if (StringUtils.isEmpty(redisCode)) {
            throw new CustomException("短信验证码已失效，请重新发送");
        }

        if (!redisCode.equals(domain.getCode())) {
            throw new CustomException("短信验证码错误，请重试");
        }

        domain.setStatus(99);
        checkoutMapper.insert(domain);

        if (StringUtils.isEmpty(domain.getClearingOrderIds())) {
            asyncService.updateCheckoutByOperatorAsync(domain.getOperatorId(), domain.getClearingCheckoutId());
        } else {
            asyncService.updateCheckoutByOrderIdsAsync(domain.getClearingOrderIds(), domain.getClearingCheckoutId());
        }


//        executorService.execute(new Runnable() {
//            @Override
//            public void run() {
//                if (StringUtils.isEmpty(domain.getClearingOrderIds())) {
//                    asyncService.updateCheckoutByOperatorAsync(domain.getOperatorId(), domain.getClearingCheckoutId());
//                } else {
//                    asyncService.updateCheckoutByOrderIdsAsync(domain.getClearingOrderIds(), domain.getClearingCheckoutId());
//                }
//            }
//        });
        return true;
    }


    @Override
    public void bankExport(HttpServletResponse response, String checkoutIds) throws IOException {

        List<CheckoutBankVo> list = checkoutMapper.selectOrderMapByCheckoutIds(checkoutIds);

        BigExcelWriter writer = ExcelUtil.getBigWriter("xhpc_clearing_checkout" + System.currentTimeMillis() + ".xlsx");

        writer.addHeaderAlias("curreyType", "币种");
        writer.addHeaderAlias("date", "日期");
        writer.addHeaderAlias("detailFlag", "明细标志");
        writer.addHeaderAlias("index", "顺序号");
        writer.addHeaderAlias("payBank", "付款帐号开户行");
        writer.addHeaderAlias("payBankAccount", "付款帐号/卡号");
        writer.addHeaderAlias("payBankName", "付款账号名称/卡名称");
        writer.addHeaderAlias("receiveBank", "收款账号开户行");
        writer.addHeaderAlias("receiveProvice", "收款账号省份");
        writer.addHeaderAlias("receiveCity", "收款账号地市");
        writer.addHeaderAlias("receiveCode", "收款账号地区码");
        writer.addHeaderAlias("receiveAccount", "收款账号");
        writer.addHeaderAlias("receiveName", "收款账号名称");
        writer.addHeaderAlias("amount", "金额");
        writer.addHeaderAlias("purposes", "汇款用途");
        writer.addHeaderAlias("remark", "备注信息");
        writer.addHeaderAlias("transType", "汇款方式");
        writer.addHeaderAlias("mobile", "收款账户短信通知手机号");
        writer.addHeaderAlias("customeIndex", "自定义序号");
        writer.addHeaderAlias("applyCheckNo", "预先审批编号");

        writer.setOnlyAlias(true);
        writer.write(list, true);
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        ServletOutputStream out = response.getOutputStream();
        writer.flush(out, true);
        writer.close();
        IoUtil.close(out);

//        com.xhpc.common.core.utils.poi.ExcelUtil<CheckoutBankVo> util = new com.xhpc.common.core.utils.poi.ExcelUtil<CheckoutBankVo>(CheckoutBankVo.class);
//        util.exportExcel(response, list, "待提现订单列表");

//        ExcelWriter writer = ExcelUtil.getWriter(true);
//        writer.addHeaderAlias("curreyType", "币种");
//        writer.addHeaderAlias("date", "日期");
//        writer.addHeaderAlias("detailFlag", "明细标志");
//        writer.addHeaderAlias("index", "顺序号");
//        writer.addHeaderAlias("payBank", "付款帐号开户行");
//        writer.addHeaderAlias("payBankAccount", "付款帐号/卡号");
//        writer.addHeaderAlias("payBankName", "付款账号名称/卡名称");
//        writer.addHeaderAlias("receiveBank", "收款账号开户行");
//        writer.addHeaderAlias("receiveProvice", "收款账号省份");
//        writer.addHeaderAlias("receiveCity", "收款账号地市");
//        writer.addHeaderAlias("receiveCode", "收款账号地区码");
//        writer.addHeaderAlias("receiveAccount", "收款账号");
//        writer.addHeaderAlias("receiveName", "收款账号名称");
//        writer.addHeaderAlias("amount", "金额");
//        writer.addHeaderAlias("purposes", "汇款用途");
//        writer.addHeaderAlias("remark", "备注信息");
//        writer.addHeaderAlias("transType", "汇款方式");
//        writer.addHeaderAlias("mobile", "收款账户短信通知手机号");
//        writer.addHeaderAlias("customeIndex", "自定义序号");
//        writer.addHeaderAlias("applyCheckNo", "预先审批编号");
//
//        writer.setOnlyAlias(true);
//        writer.write(list, true);
//        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
//        response.setCharacterEncoding("utf-8");
//        ServletOutputStream out = response.getOutputStream();
//        writer.flush(out, true);
//        writer.close();
//        IoUtil.close(out);
    }


    @Override
    public void orderExport(HttpServletResponse response, String checkoutIds) throws IOException {
        Map<String, Object> params = new HashMap<>();
        params.put("checkoutIds", checkoutIds);

        List<XhpcClearingHistoryOrderDomain> list = historyOrderMapper.getListPage(params);

        // 通过工具类创建writer，默认创建xls格式
        BigExcelWriter writer = ExcelUtil.getBigWriter("HistoryOrder_" + System.currentTimeMillis() + ".xlsx");
        writer.addHeaderAlias("serialNumber", "订单号");
        writer.addHeaderAlias("sourceName", "用户类型");
        writer.addHeaderAlias("chargingModeName", "流量方名称");
        writer.addHeaderAlias("stationName", "电站名称");
        writer.addHeaderAlias("terminalName", "终端名称");
        writer.addHeaderAlias("operatorName", "运营商");
        writer.addHeaderAlias("powerPriceTotal", "电费（元）");
        writer.addHeaderAlias("servicePriceTotal", "服务费（元）");
        writer.addHeaderAlias("totalPrice", "订单总金额（元）");
        writer.addHeaderAlias("promotionDiscount", "抵扣总金额（元）");
        writer.addHeaderAlias("actPrice", "用户支付的金额（元）");
        writer.addHeaderAlias("internetCommission", "流量方总金额抽成（元）");
        writer.addHeaderAlias("internetSvcCommission", "流量方服务费抽成（元）");
        writer.addHeaderAlias("internetDegreeCommission", "流量方电量抽成（元）");
        writer.addHeaderAlias("platformCommission", "平台总金额抽成（元）");
        writer.addHeaderAlias("platformSvcCommisssion", "平台服务费抽成（元）");
        writer.addHeaderAlias("operationCommission", "运维总抽成（元）");
        writer.addHeaderAlias("operationSvcCommission", "运维服务费抽成（元）");
        writer.addHeaderAlias("actPowerPrice", "运营商实收电费（元）");
        writer.addHeaderAlias("actServicePrice", "运营商实收服务费（元）");
        writer.addHeaderAlias("clearingPrice", "运营商不参与清分金额（元）");
        writer.addHeaderAlias("startSoc", "启动SOC");
        writer.addHeaderAlias("endSoc", "结算SOC");
        writer.addHeaderAlias("startTime", "开始充电时间");
        writer.addHeaderAlias("endTime", "结束充电时间");
        // 默认的，未添加alias的属性也会写出，如果想只写出加了别名的字段，可以调用此方法排除之
        writer.setOnlyAlias(true);
        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(list, true);
        //out为OutputStream，需要写出到的目标流
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
//        //response为HttpServletResponse对象
//        response.setContentType("application/vnd.ms-excel;charset=utf-8");
//        //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
//        response.setHeader("Content-Disposition", "attachment;filename=历史订单列表.xls");
        ServletOutputStream out = response.getOutputStream();

        writer.flush(out, true);
        // 关闭writer，释放内存
        writer.close();
        //此处记得关闭输出Servlet流
        IoUtil.close(out);
    }


    @Override
    public boolean insertReceipt(ClearingReceiptVo receiptVo) throws Exception {
        String fileUrl = receiptVo.getFile();
        if (!fileUrl.startsWith("http")) {
            String domain = ossProperties.getDomain();
            if (!domain.endsWith("/")) {
                domain = domain + "/";
            }
            fileUrl = domain + fileUrl;
        }

        File dataFile = DownloadUtil.downloadFile(fileUrl);
        com.xhpc.common.core.utils.poi.ExcelUtil<CheckoutBankVo> util = new com.xhpc.common.core.utils.poi.ExcelUtil<CheckoutBankVo>(CheckoutBankVo.class);
        List<CheckoutBankVo> checkoutList = util.importExcel(new FileInputStream(dataFile));
        if(checkoutList.size() < 1){
            throw new CustomException("请检查表格数据是否正确");
        }

        String checkoutIds = checkoutList.stream().map(CheckoutBankVo::getIndex).collect(Collectors.joining(","));
        if(StringUtils.isEmpty(checkoutIds)){
            throw new CustomException("请检查表格中是否包括“顺序号”列");
        }
        String unReceiptIds = checkoutMapper.selectIdsByStatusAndIds(checkoutIds, 1);

        if (StringUtils.isNotEmpty(unReceiptIds)) {
            List<XhpcClearingReceiptDomain> receiptDomainList = receiptVo.getReceiptList();
            for (XhpcClearingReceiptDomain receiptDomain : receiptDomainList) {
                receiptDomain.setClearingCheckoutIds(unReceiptIds);
            }
            receiptMapper.insretBatch(receiptDomainList);
            checkoutMapper.updateStatusByIds(unReceiptIds, 6);
        }
        return true;
    }


    @Override
    public List<Map<String, Object>> getListPage(String phone, String transactionNumber, Integer status, String chargingStationName, Long operatorId, Integer source, String beginStartTime, String beginEndTime, Long userId, Integer type, String affiliationOrganization, String evcsOrderNo, String plateNum, Integer internetId, String internetSerialNumber, String terminalName, String vinCode, String overStartTime, String overEndTime, Long personnelId, Integer confirmResult, Integer checkoutId) {

        Integer number = 0;
        //电话和用户类型都不为null  number =3
        //电话不为null，用户类型为null  number =1
        //电话为null，用户类型不为null  number=2
        //电话为null，用户类型为null  number=0
        if (!"".equals(phone) && phone != null && !"".equals(source) && source != null) {
            number = 3;
        } else if (!"".equals(phone) && phone != null && source == null) {
            number = 1;
        } else if (phone == null && source != null) {
            number = 2;
        }
        //获取登陆用户
        Long logUserId = SecurityUtils.getUserId();
        LoginUser loginUser = tokenService.getLoginUser();
        String tenantId = loginUser.getTenantId();
        //桩的统计、该时段金额
        List<Map<String, Object>> list = new ArrayList<>();
        if (!userId.equals(UserTypeUtil.USER_ID)) {
            Map<String, Object> landUser = historyOrderMapper.getLandUser(logUserId);
            if (landUser != null) {
                if (landUser.get("userType") != null) {
                    startPage();
                    if (UserTypeUtil.SYS_USER_TYPE_ONE.equals(landUser.get("userType").toString())) {
                        Long logOperatorId = Long.valueOf(landUser.get("operatorId").toString());
                        //运营商看自己的场站
                        list = historyOrderMapper.getOrderListPage(phone, transactionNumber, 1, chargingStationName, operatorId, source, beginStartTime, beginEndTime, logOperatorId, type, number, affiliationOrganization, evcsOrderNo, plateNum, internetId, internetSerialNumber, terminalName, vinCode, overStartTime, overEndTime, personnelId, confirmResult, tenantId, 0, checkoutId);
                    } else {
                        //查询赋值的场站
                        list = historyOrderMapper.getOrderListPage(phone, transactionNumber, 2, chargingStationName, operatorId, source, beginStartTime, beginEndTime, logUserId, type, number, affiliationOrganization, evcsOrderNo, plateNum, internetId, internetSerialNumber, terminalName, vinCode, overStartTime, overEndTime, personnelId, confirmResult, tenantId, 0, checkoutId);
                    }
                }
            }

        } else {
            startPage();
            list = historyOrderMapper.getOrderListPage(phone, transactionNumber, 0, chargingStationName, operatorId, source, beginStartTime, beginEndTime, userId, type, number, affiliationOrganization, evcsOrderNo, plateNum, internetId, internetSerialNumber, terminalName, vinCode, overStartTime, overEndTime, personnelId, confirmResult, tenantId, 0, checkoutId);
        }
        return list;
    }



    @Override
    public void getListPageExport(HttpServletResponse response,String phone, String transactionNumber, Integer status, String chargingStationName, Long operatorId, Integer source, String beginStartTime, String beginEndTime, Long userId, Integer type, String affiliationOrganization, String evcsOrderNo, String plateNum, Integer internetId, String internetSerialNumber, String terminalName, String vinCode, String overStartTime, String overEndTime, Long personnelId, Integer confirmResult, Integer checkoutId) throws IOException {

        Integer number = 0;
        if (!"".equals(phone) && phone != null && !"".equals(source) && source != null) {
            number = 3;
        } else if (!"".equals(phone) && phone != null && source == null) {
            number = 1;
        } else if (phone == null && source != null) {
            number = 2;
        }
        //获取登陆用户
        Long logUserId = SecurityUtils.getUserId();
        LoginUser loginUser = tokenService.getLoginUser();
        String tenantId = loginUser.getTenantId();
        //桩的统计、该时段金额
        List<Map<String, Object>> list = new ArrayList<>();
        if (!userId.equals(UserTypeUtil.USER_ID)) {
            Map<String, Object> landUser = historyOrderMapper.getLandUser(logUserId);
            if (landUser != null) {
                if (landUser.get("userType") != null) {
                    startPage();
                    if (UserTypeUtil.SYS_USER_TYPE_ONE.equals(landUser.get("userType").toString())) {
                        Long logOperatorId = Long.valueOf(landUser.get("operatorId").toString());
                        //运营商看自己的场站
                        list = historyOrderMapper.getOrderListPage(phone, transactionNumber, 1, chargingStationName, operatorId, source, beginStartTime, beginEndTime, logOperatorId, type, number, affiliationOrganization, evcsOrderNo, plateNum, internetId, internetSerialNumber, terminalName, vinCode, overStartTime, overEndTime, personnelId, confirmResult, tenantId, 0, checkoutId);
                    } else {
                        //查询赋值的场站
                        list = historyOrderMapper.getOrderListPage(phone, transactionNumber, 2, chargingStationName, operatorId, source, beginStartTime, beginEndTime, logUserId, type, number, affiliationOrganization, evcsOrderNo, plateNum, internetId, internetSerialNumber, terminalName, vinCode, overStartTime, overEndTime, personnelId, confirmResult, tenantId, 0, checkoutId);
                    }
                }
            }

        } else {
            startPage();
            list = historyOrderMapper.getOrderListPage(phone, transactionNumber, 0, chargingStationName, operatorId, source, beginStartTime, beginEndTime, userId, type, number, affiliationOrganization, evcsOrderNo, plateNum, internetId, internetSerialNumber, terminalName, vinCode, overStartTime, overEndTime, personnelId, confirmResult, tenantId, 0, checkoutId);
        }


        Map<String, Object> params = new HashMap<>();
        // 通过工具类创建writer，默认创建xls格式
        BigExcelWriter writer = ExcelUtil.getBigWriter("HistoryOrder_" + System.currentTimeMillis() + ".xlsx");
        writer.addHeaderAlias("serialNumber", "订单号");
        writer.addHeaderAlias("sourceName", "用户类型");
        writer.addHeaderAlias("chargingModeName", "流量方名称");
        writer.addHeaderAlias("chargingStationName", "电站名称");
        writer.addHeaderAlias("terminalName", "终端名称");
        writer.addHeaderAlias("operatorName", "运营商");
        writer.addHeaderAlias("totalPower", "电量");
        writer.addHeaderAlias("powerPriceTotal", "电费（元）");
        writer.addHeaderAlias("servicePriceTotal", "服务费（元）");
        writer.addHeaderAlias("totalPrice", "订单总金额（元）");
        writer.addHeaderAlias("promotionDiscount", "抵扣总金额（元）");
        writer.addHeaderAlias("actPrice", "用户支付的金额（元）");
        writer.addHeaderAlias("internetCommission", "流量方总金额抽成（元）");
        writer.addHeaderAlias("internetSvcCommission", "流量方服务费抽成（元）");
        writer.addHeaderAlias("internetDegreeCommission", "流量方电量抽成（元）");
        writer.addHeaderAlias("platformCommission", "平台总金额抽成（元）");
        writer.addHeaderAlias("platformSvcCommisssion", "平台服务费抽成（元）");
        writer.addHeaderAlias("operationCommission", "运维总抽成（元）");
        writer.addHeaderAlias("operationSvcCommission", "运维服务费抽成（元）");
        writer.addHeaderAlias("actPowerPrice", "运营商实收电费（元）");
        writer.addHeaderAlias("actServicePrice", "运营商实收服务费（元）");
        writer.addHeaderAlias("clearingPrice", "运营商不参与清分金额（元）");
        writer.addHeaderAlias("startSoc", "启动SOC");
        writer.addHeaderAlias("endSoc", "结算SOC");
        writer.addHeaderAlias("startTime", "开始充电时间");
        writer.addHeaderAlias("endTime", "结束充电时间");
        // 默认的，未添加alias的属性也会写出，如果想只写出加了别名的字段，可以调用此方法排除之
        writer.setOnlyAlias(true);
        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(list, true);
        //out为OutputStream，需要写出到的目标流
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
//        //response为HttpServletResponse对象
//        response.setContentType("application/vnd.ms-excel;charset=utf-8");
//        //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
//        response.setHeader("Content-Disposition", "attachment;filename=历史订单列表.xls");
        ServletOutputStream out = response.getOutputStream();

        writer.flush(out, true);
        // 关闭writer，释放内存
        writer.close();
        //此处记得关闭输出Servlet流
        IoUtil.close(out);


    }
}
