package com.ywt.service;

import com.ywt.config.ParameterConfigurer;
import com.ywt.core.BaseResponse;
import com.ywt.core.DataResponse;
import com.ywt.core.PagedList;
import com.ywt.core.SqlHelper;
import com.ywt.core.utils.Checker;
import com.ywt.core.utils.DateUtil;
import com.ywt.core.utils.ExcelHelper;
import com.ywt.core.utils.FormatUtil;
import com.ywt.core.utils.serializers.JsonSerializer;
import com.ywt.domain.entity.center.Hospital;
import com.ywt.domain.entity.center.HospitalRepository;
import com.ywt.domain.entity.glasses.*;
import com.ywt.domain.models.ConstantDef;
import com.ywt.domain.models.enums.*;

import com.ywt.interceptors.WebAppContext;
import com.ywt.params.api.order.*;
import com.ywt.params.mg.order.AmountListRequest;
import com.ywt.service.common.OrderCenterService;
import com.ywt.service.common.WeChatService;
import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableCellFormat;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import org.apache.dubbo.config.annotation.DubboService;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

@DubboService
@Service
public class GoodsOrdersService extends ServiceBase {

    private static final Logger logger = LoggerFactory.getLogger(GoodsOrdersService.class);

    @Autowired
    private GoodsOrdersRepository goodsOrdersRepository;

    @Autowired
    private GoodsOrdersDetailRepository goodsOrdersDetailRepository;

    @Autowired
    private PostAddressRepository postAddressRepository;

    @Autowired
    private DictTypeService dictTypeService;

    @Autowired
    private UserService userService;

    @Autowired
    private HospitalRepository hospitalRepository;

    @Autowired
    private OrderCenterService orderCenterService;

    @Autowired
    private ParameterConfigurer parameterConfigurer;

    @Autowired
    @Qualifier("sqlHelperGlasses")
    private SqlHelper sqlHelperGlasses;

    @Autowired
    @Qualifier("glassesJdbcTemplate")
    private JdbcTemplate glassesJdbcTemplate;

    @Autowired
    private GlassesIdGenerator glassesIdGenerator;

    @Autowired
    private WeChatService weChatService;

    @Autowired
    private MgGoodsOrdersService mgGoodsOrdersService;

    public GoodsOrders getGoodsOrdersByOrderId(int orderId) {
        return goodsOrdersRepository.findByOrderId(orderId);
    }

    public GoodsOrders getGoodsOrdersById(int goodsOrdersId) {
        return goodsOrdersRepository.findById(goodsOrdersId);
    }

    public List<GoodsOrdersDetail> getGoodsOrdersDetailListByOrderId(int goodsOrdersId) {
        return goodsOrdersDetailRepository.findByGoodsOrdersId(goodsOrdersId);
    }

    public PostAddress getPostAddressById(int addressId) {
        return postAddressRepository.findOneById(addressId);
    }

    public DataResponse<GetOrderDetailResponse> getOrderDetail(GetOrderDetailRequest request) {
        DataResponse<GetOrderDetailResponse> response = new DataResponse<>();
        int goodsOrdersId = request.getGoodsOrdersId();
        GoodsOrders orders = getGoodsOrdersById(goodsOrdersId);
        if (Checker.isNone(orders)) {
            return response.failedWithParameterError("该订单不存在");
        }
        List<GoodsOrdersDetail> goodsOrdersDetailList = getGoodsOrdersDetailListByOrderId(orders.getId());
        PostAddress address = null;
        int getChannel = Checker.getIntegerValue(orders.getGetChannel());
        if (getChannel == GetChannelEnum.MAIL.getValue()) {
            address = getPostAddressById(orders.getAddressId());
        }
        GetOrderDetailResponse orderResponse = new GetOrderDetailResponse();
        orderResponse.setGoodsOrdersId(orders.getId());
        orderResponse.setOrderId(orders.getOrderId());
        orderResponse.setOrderNo(orders.getOrderNo());
        orderResponse.setPatientName(orders.getPatientName());
        orderResponse.setMobile(orders.getMobile());
        orderResponse.setSex(SexEnum.getSexDisplayName(Checker.getIntegerValue(orders.getSex())));
        orderResponse.setAge(orders.getAge());
        orderResponse.setPayAmount(FormatUtil.intShrink100ToStr(orders.getPayAmount()));
        orderResponse.setPayAmountInt(Checker.getIntegerValue(orders.getPayAmount()));
        orderResponse.setGetChannel(Checker.getIntegerValue(orders.getGetChannel()));
        int statusInt = Checker.getIntegerValue(orders.getStatus());
        orderResponse.setStatus(statusInt);
        orderResponse.setStatusStr(GoodsOrdersStatusEnum.valueOf(statusInt).getDisplayName());
        String qrCodeUrl = parameterConfigurer.getYwtHttpsMsiteDomain() + String.format(ConstantDef.NFYYBYFY_GOODS_ORDERS_DETAIL_URL, goodsOrdersId);
        orderResponse.setQrCodeUrl(qrCodeUrl);
        // 得到镜片参数
        GoodsParmVO glassesParam = getGlassesParam(Checker.getStringValue(orders.getGlassesParam()));
        // 得到邮寄地址
        PostAddressVO postAddressVO = getPostAddressVO(address);
        // 得到订单商品详情列表
        List<GoodsOrderDetailVO> goodsOrderDetailList = getGoodsOrderDetailList(goodsOrdersDetailList);
        orderResponse.setGlassesParam(glassesParam);
        orderResponse.setPostAddress(postAddressVO);
        orderResponse.setOrderDetailList(goodsOrderDetailList);
        response.setData(orderResponse);
        response.succeed();
        return response;
    }

    private List<GoodsOrderDetailVO> getGoodsOrderDetailList(List<GoodsOrdersDetail> goodsOrdersDetailList) {
        List<GoodsOrderDetailVO> goodsOrderDetailVoList = new ArrayList<>();
        if (!Checker.isNone(goodsOrdersDetailList)) {
            for (GoodsOrdersDetail detail : goodsOrdersDetailList) {
                GoodsOrderDetailVO vo = new GoodsOrderDetailVO();
                vo.setDetailId(detail.getId());
                vo.setOrderId(detail.getGoodsOrdersId());
                vo.setGoodsId(detail.getGoodsId());
                vo.setGoodsName(detail.getGoodsName());
                vo.setGoodsNumber(detail.getGoodsNumber());
                vo.setGoodsPrice(FormatUtil.intShrink100ToStr(detail.getGoodsPrice()));
                vo.setGoodsPic(detail.getGoodsPic());
                vo.setPayAmount(FormatUtil.intShrink100ToStr(detail.getPayAmount()));
                vo.setGoodsPriceInt(Checker.getIntegerValue(detail.getGoodsPrice()));
                vo.setPayAmountInt(Checker.getIntegerValue(detail.getPayAmount()));
                vo.setDiscount(detail.getDiscount());
                vo.setRemark(Checker.getStringValue(detail.getRemark()));
                goodsOrderDetailVoList.add(vo);
            }
        }
        return goodsOrderDetailVoList;
    }

    private PostAddressVO getPostAddressVO(PostAddress address) {
        PostAddressVO postAddressVO = new PostAddressVO();
        if (!Checker.isNone(address)) {
            postAddressVO.setAddressId(address.getId());
            postAddressVO.setName(address.getName());
            postAddressVO.setMobile(address.getMobile());
            postAddressVO.setProvince(address.getProvince());
            postAddressVO.setCity(address.getCity());
            postAddressVO.setArea(address.getArea());
            postAddressVO.setAddress(address.getAddress());
            String allAddress = address.getProvince() + address.getCity() + address.getArea() + address.getAddress();
            postAddressVO.setAllAddress(allAddress);
        }
        return postAddressVO;
    }

    private GoodsParmVO getGlassesParam(String param) {
        // 如果不为空，对数据进行解析
        try {
            if (!Checker.isNone(param)) {
                GoodsParmVO vo = JsonSerializer.from(param, GoodsParmVO.class);
                if (vo != null) {
                    return vo;
                }
            }
        } catch (Exception e) {
            logger.error("GoodsOrdersService#getOrderDetail(param={}):Deserialize failed!\n{}", param, e.getMessage(), e);
        }
        return new GoodsParmVO();
    }

    private PagedList<GoodsOrders> getGoodsOrdersPageList(GetGoodsOrdersListRequest request, int userId, int hospitalId) {
        int pageIndex = request.getPageIndex();
        int pageSize = request.getPageSize();

        List<Object> paramList = new ArrayList<>();
        String whereSql = " ( 1=1 ) and deleted = 0 and hospital_id = ? and user_id = ? ";
        paramList.add(hospitalId);
        paramList.add(userId);
        return sqlHelperGlasses.getPagedList(pageIndex, pageSize, "*", whereSql, "id desc", GoodsOrders.class, paramList.toArray());
    }

    public DataResponse getGoodsOrdersList(GetGoodsOrdersListRequest request) {
        DataResponse response = new DataResponse<>();
        int userId = userService.getCurrentUserId();
        if (userId == 0) {
            response.failedWithParameterError("该订单不存在");
            return response;
        }
        int hospitalId = userService.getHospitalId();
        if (hospitalId == 0) {
            hospitalId = ConstantDef.NFYYBYFY_HOSPITAL_ID;
        }
        Hospital hospital = hospitalRepository.findById(hospitalId).orElse(null);
        String hospitalName = "";
        if (!Checker.isNone(hospital)) {
            hospitalName = Checker.getStringValue(hospital.getName());
        }
        PagedList<GoodsOrders> goodsOrdersPageList = getGoodsOrdersPageList(request, userId, hospitalId);
        List<GoodsOrders> goodsOrdersList = goodsOrdersPageList.getItems();
        List<ListOrderVO> returnValue = new ArrayList<>();
        if (!Checker.isNone(goodsOrdersList)) {
            for (GoodsOrders orders : goodsOrdersList) {
                ListOrderVO vo = new ListOrderVO();
                vo.setGoodsOrdersId(orders.getId());
                vo.setOrderId(orders.getOrderId());
                vo.setOrderNo(orders.getOrderNo());
                vo.setHospitalName(hospitalName);
                vo.setDeptName("眼科");
                vo.setPatientName(Checker.getStringValue(orders.getPatientName()));
                vo.setCreateTime(FormatUtil.createTimeFormatList(orders.getCreateTime()));
                vo.setPayAmount(FormatUtil.intShrink100ToStr(orders.getPayAmount()));
                vo.setStatus(GoodsOrdersStatusEnum.valueOf(orders.getStatus()).getDisplayName());
                returnValue.add(vo);
            }
        }
        int total = goodsOrdersPageList.getTotal();
        int totalPages = sqlHelperGlasses.getTotalPages(total, request.getPageSize());
        HashMap<String, Object> map = new HashMap<>();
        map.put("list", returnValue);
        map.put("totalPages", totalPages);
        response.setData(map);
        return response;
    }

    public BaseResponse checkOrders(PayOrderRequest request) {
        DataResponse response = new DataResponse<>();
        int goodsOrdersId = request.getGoodsOrdersId();
        String payAmount = request.getPayAmount();
        GoodsOrders orders = getGoodsOrdersById(goodsOrdersId);
        if (Checker.isNone(orders)) {
            return response.failedWithParameterError("该订单不存在");
        }
        if (Checker.getIntegerValue(orders.getStatus()) != GoodsOrdersStatusEnum.PendingPayment.getValue()) {
            return response.failedWithParameterError("该订单不满足支付条件");
        }
        int payAmountInt = FormatUtil.bigDecimalTo100Int(new BigDecimal(payAmount));
        if (Checker.getIntegerValue(payAmountInt) <= 0 || payAmountInt != Checker.getIntegerValue(orders.getPayAmount())) {
            return response.failedWithParameterError("支付金额有误");
        }
        // 需要判断是否有足够的库存
        List<GoodsOrdersDetail> ordersDetailList = goodsOrdersDetailRepository.findByGoodsOrdersId(goodsOrdersId);
        List<Integer> goodsIds = ordersDetailList.stream().map(GoodsOrdersDetail::getGoodsId).collect(Collectors.toList());
        List<Goods> goodsList = mgGoodsOrdersService.getGoodsListByGoodsIds(goodsIds);
        for (GoodsOrdersDetail detail : ordersDetailList) {
            Goods goods = goodsList.stream().filter(p -> p.getId().equals(detail.getGoodsId())).findFirst().orElse(null);
            if (!Checker.isNone(goods)) {
                if (goods.getInventory() - detail.getGoodsNumber() < 0) {
                    return response.failedWithParameterError(goods.getName() + "库存不足");
                }
            }
        }
        try {
            int userId = userService.getCurrentUserId();
            int terminal = userService.getCurrentTerminal();
            String openId = userService.getCurrentOpenId();
            String ip = WebAppContext.current().getIP();
            logger.info("GoodsOrdersService#payOrder() -- print --:map: {},userId: {}, terminal: {}, openId: {}",
                    JsonSerializer.toJson(request), userId, terminal, openId);

            if (userId == 0 || Checker.isNone(openId)) {
                return response.failedWithParameterError("无法确定用户身份，请先授权");
            }
            orders.setUserId(userId);
            goodsOrdersRepository.save(orders);
            return response.succeed("库存充足");
        } catch (
                Exception e) {
            logger.error("GoodsOrdersService#payOrder(): {}", e.getMessage(), e);
            return response.failed(BaseResponse.APP_EXCEPTION, e.getMessage());
        }
    }

    private List<GoodsOrders> getGoodsOrdersList(AmountListRequest request, int paymentStatus, int shopId) throws Exception {

        List<Object> paramList = new ArrayList<>();
        String whereSql = " ( 1=1 ) and deleted = 0 and payment_status = ? and (refund_status is null or refund_status != 1) and shop_id = ? ";
        paramList.add(paymentStatus);
        paramList.add(shopId);

        // 时间查询处理
        String createTimeStart = request.getCreateTime();
        String createTimeEnd = request.getCreateEndTime();
        Map<String, Object> map = sqlHelperGlasses.timeQuerySql(whereSql, paramList, "create_time", createTimeStart, createTimeEnd);
        whereSql = (String) map.get("whereSql");
        paramList = (List<Object>) map.get("paramList");

        return sqlHelperGlasses.getList("*", whereSql, "id desc", GoodsOrders.class, paramList.toArray());
    }

    public BaseResponse amountList(AmountListRequest request) throws Exception {
        DataResponse response = new DataResponse();
        Map<String, Object> items = new HashMap<>();
        int shopId = userService.getShopId();
        shopId = shopId > 0 ? shopId : 1;
        // 得到支付的数据
        List<GoodsOrders> payOrderList = getGoodsOrdersList(request, PaymentStatusEnum.Success.getValue(), shopId);
        //支付方式
        List<Map<String, Object>> payList = amountListNew(payOrderList);
        //营业统计
        List<Map<String, Object>> businessList = amountListPostNew(payOrderList);
        items.put("payList", payList);
        items.put("businessList", businessList);
        response.setData(items);
        return response.succeed("成功");
    }

    private List<Map<String, Object>> amountListNew(List<GoodsOrders> payOrderList) {
        ArrayList<Map<String, Object>> list = new ArrayList<>();
        List<Integer> paymentChannelList = new ArrayList<>();
        paymentChannelList.add(PaymentChannelEnum.WeChat.getValue());
        paymentChannelList.add(PaymentChannelEnum.Cash.getValue());
        if (!Checker.isNone(paymentChannelList)) {
            int totalOrderQuantity = 0, totalOrderAmount = 0;
            for (Integer paymentChannel : paymentChannelList) {
                HashMap<String, Object> item = new HashMap<>();

                item.put("paymentChannel", paymentChannel);
                String paymentChannelStr = PaymentChannelEnum.valueOf(paymentChannel).getDisplayName();
                if (paymentChannel == PaymentChannelEnum.Cash.getValue()) {
                    paymentChannelStr = "其它支付方式";
                }
                item.put("paymentChannelStr", paymentChannelStr);

                long orderQuantity = 0L;
                int orderAmount = 0;
                if (!Checker.isNone(payOrderList)) {
                    orderQuantity = payOrderList.stream().filter(p -> Checker.getIntegerValue(p.getPaymentChannel()) == paymentChannel).count();
                    orderAmount = payOrderList.stream().filter(p -> Checker.getIntegerValue(p.getPaymentChannel()) == paymentChannel).mapToInt(GoodsOrders::getPayAmount).sum();
                }
                item.put("orderQuantity", orderQuantity);
                item.put("orderAmount", orderAmount);
                item.put("orderAmountStr", FormatUtil.intShrink100ToStr(orderAmount));

                totalOrderQuantity += orderQuantity;
                totalOrderAmount += orderAmount;
                list.add(item);
            }
            HashMap<String, Object> item = new HashMap<>();
            item.put("paymentChannel", -1);
            String paymentChannelStr = "合计";
            item.put("paymentChannelStr", paymentChannelStr);
            item.put("orderQuantity", totalOrderQuantity);
            item.put("orderAmount", totalOrderAmount);
            item.put("orderAmountStr", FormatUtil.intShrink100ToStr(totalOrderAmount));
            list.add(item);
        }
        return list;
    }


    private List<Map<String, Object>> amountListPostNew(List<GoodsOrders> payOrderList) {
        ArrayList<Map<String, Object>> list = new ArrayList<>();
        List<Integer> getChannelList = new ArrayList<>();
        getChannelList.add(GetChannelEnum.INVITE.getValue());
        getChannelList.add(GetChannelEnum.MAIL.getValue());
        if (!Checker.isNone(getChannelList)) {
            int totalOrderQuantity = 0, totalOrderAmount = 0;
            for (Integer getChannel : getChannelList) {
                HashMap<String, Object> item = new HashMap<>();

                item.put("getChannel", getChannel);
                String getChannelStr = GetChannelEnum.valueOf(getChannel).getDisplayName() + "单数";
                item.put("getChannelStr", getChannelStr);

                long orderQuantity = 0L;
                int orderAmount = 0;
                if (!Checker.isNone(payOrderList)) {
                    orderQuantity = payOrderList.stream().filter(p -> Checker.getIntegerValue(p.getGetChannel()) == getChannel).count();
                    orderAmount = payOrderList.stream().filter(p -> Checker.getIntegerValue(p.getGetChannel()) == getChannel).mapToInt(GoodsOrders::getPayAmount).sum();
                }
                item.put("orderQuantity", orderQuantity);
                item.put("orderAmount", orderAmount);
                item.put("orderAmountStr", FormatUtil.intShrink100ToStr(orderAmount));

                // 计算单均消费
                DecimalFormat df = new DecimalFormat("0.00");
                String average = "0.00";
                if (orderQuantity > 0) {
                    average = df.format(new BigDecimal(orderAmount)
                            .divide(new BigDecimal("100"))
                            .divide(new BigDecimal(orderQuantity)).doubleValue());
                }
                item.put("averageAmountStr", average);

                totalOrderQuantity += orderQuantity;
                totalOrderAmount += orderAmount;
                list.add(item);
            }
            HashMap<String, Object> item = new HashMap<>();
            item.put("getChannel", -1);
            String getChannelStr = "总单数";
            item.put("getChannelStr", getChannelStr);
            item.put("orderQuantity", totalOrderQuantity);
            item.put("orderAmount", totalOrderAmount);
            item.put("orderAmountStr", FormatUtil.intShrink100ToStr(totalOrderAmount));

            // 计算单均消费
            DecimalFormat df = new DecimalFormat("0.00");
            String average = "0.00";
            if (totalOrderAmount > 0) {
                average = df.format(new BigDecimal(totalOrderAmount)
                        .divide(new BigDecimal("100"))
                        .divide(new BigDecimal(totalOrderQuantity)).doubleValue());
            }
            item.put("averageAmountStr", average);
            list.add(item);
        }
        return list;
    }

    public BaseResponse saveMailAddress(SaveMailAddressRequest request) throws Exception {
        BaseResponse response = new BaseResponse();
        int goodsOrdersId = request.getGoodsOrdersId();
        if (goodsOrdersId <= 0) {
            return response.failedWithParameterError("订单ID有误");
        }
        GoodsOrders goodsOrders = goodsOrdersRepository.findById(goodsOrdersId);
        if (Checker.isNone(goodsOrders)) {
            return response.failedWithParameterError("该订单不存在");
        }
        int getChannel = Checker.getIntegerValue(request.getGetChannel());
        goodsOrders.setGetChannel(getChannel);
        if (getChannel == GetChannelEnum.INVITE.getValue()) {
            goodsOrders.setAddressId(0);
            goodsOrdersRepository.save(goodsOrders);
            return response.succeed();
        }
        boolean boo = getChannel == GetChannelEnum.MAIL.getValue()
                && (
                Checker.isNone(request.getName()) || Checker.isNone(request.getMobile())
                        || Checker.isNone(request.getProvince()) || Checker.isNone(request.getCity())
                        || ((!request.getProvince().equals("台湾省")) && Checker.isNone(request.getArea())) || Checker.isNone(request.getAddress())
        );
        if (boo) {
            return response.failedWithParameterError("请先填写邮寄地址");
        }
        PostAddress address = new PostAddress();
        int addressId = glassesIdGenerator.genPostAddressId();
        address.setId(addressId);
        address.setMobile(request.getMobile());
        address.setName(request.getName());
        address.setAddressIds(request.getAddressIds());
        address.setProvince(request.getProvince());
        address.setCity(request.getCity());
        address.setArea(request.getArea());
        address.setAddress(request.getAddress());
        address.setDeleted(0);
        address.setCreatTime(new Date());
        address.setUpdateTime(new Date());

        goodsOrders.setAddressId(addressId);
        postAddressRepository.save(address);
        goodsOrdersRepository.save(goodsOrders);
        return response.succeed();
    }

    private List<DownloadOrdersDetailVO> getDownloadOrdersDetailList(AmountListRequest request, int paymentStatus, int shopId) throws Exception {
        List<Object> paramList = new ArrayList<>();
        String whereSql = " ( 1=1 ) and g.deleted = 0 and g.payment_status = ? and (g.refund_status is null or g.refund_status != 1) and g.shop_id = ? and g.id = d.goods_orders_id ";
        paramList.add(paymentStatus);
        paramList.add(shopId);
        // 时间查询处理
        String createTimeStart = request.getCreateTime();
        String createTimeEnd = request.getCreateEndTime();
        Map<String, Object> map = sqlHelperGlasses.timeQuerySql(whereSql, paramList, "g.create_time", createTimeStart, createTimeEnd);
        whereSql = (String) map.get("whereSql");
        paramList = (List<Object>) map.get("paramList");
        String fields = " g.id as goodsOrdersId, " +
                " g.order_no as orderNo, " +
                " g.get_channel as getChannel," +
                " d.goods_id as goodsId, " +
                " d.goods_name as goodsName," +
                " d.type_name as typeName, " +
                " d.goods_spec as goodsSpec, " +
                " d.goods_price as goodsPriceInt, " +
                " d.goods_number as goodsNumber, " +
                " d.pay_amount as payAmountInt, " +
                " g.create_time as createTimeDate, " +
                " g.payment_time as paymentTimeDate, " +
                " g.refund_time as refundTimeDate ";
        String dataSource = " goods_orders g, goods_orders_detail d ";
        return sqlHelperGlasses.getMultipleTableDownLoadList(fields, dataSource, whereSql, " d.id desc", paramList.toArray(), DownloadOrdersDetailVO.class);
    }

    public void downloadBillOrderList(AmountListRequest request, HttpServletResponse httpServletResponse) {
        String filename = "眼镜数据";
        OutputStream out = null;
        WritableWorkbook workbook = null;
        try {
            String createTime = request.getCreateTime();
            String createEndTime = request.getCreateEndTime();
            if (!Checker.isNone(createTime) && !Checker.isNone(createEndTime)) {
                filename += createTime.replace("-", "") + "~" + createEndTime.replace("-", "");
            }
            ExcelHelper.setHttpServletResponse(httpServletResponse, filename + ".xls");
            out = httpServletResponse.getOutputStream();
            // 创建写工作簿对象
            workbook = Workbook.createWorkbook(out);
            // 工作表（设置第一个sheet）
            WritableSheet sheet = workbook.createSheet(filename, 0);
            // 设置第一行格式
            WritableCellFormat cellFormat = ExcelHelper.getWritableCellFormat();
            // 设置列的不同宽度;
            Map<Integer, Integer> widthSet = new HashMap<>(16);
            widthSet.put(0, 35);
            widthSet.put(8, 35);
            widthSet.put(9, 35);
            widthSet.put(10, 35);
            ExcelHelper.settingColumnWidth(sheet, widthSet);
            String[] title = new String[]{"订单号", "取货方式", "名称", "类型", "规格", "单价", "数量", "合计", "创建时间", "支付时间", "退费时间"};

            // 第二行格式
            ExcelHelper.settingTitleLabelCell(sheet, cellFormat, title);
            int n = 1;
            // 第二行格式
            WritableCellFormat cellFormat2 = ExcelHelper.getWritableCellFormat();

            // 得到支付的数据
            int shopId = Checker.getIntegerValue(request.getShopId());
            if (shopId == 0) {
                int currentShopId = userService.getShopId();
                shopId = currentShopId > 0 ? currentShopId : 1;
            }
            List<DownloadOrdersDetailVO> downloadOrdersDetailList = getDownloadOrdersDetailList(request, PaymentStatusEnum.Success.getValue(), shopId);
            detailExcel(downloadOrdersDetailList, n, cellFormat2, sheet);
            workbook.write();

        } catch (Exception e) {
            if (out != null) {
                e.printStackTrace();
            }
            logger.error("/mg/order/downloadBillOrderList(): {}", e.getMessage(), e);
        } finally {
            if (workbook != null) {
                try {
                    workbook.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 得到excel订单列表
     *
     * @param downloadOrdersDetailList {@link List<DownloadOrdersDetailVO>}
     * @param n                        行数
     * @param cellFormat2
     * @param sheet
     * @throws Exception
     */
    private void detailExcel(List<DownloadOrdersDetailVO> downloadOrdersDetailList, int n, WritableCellFormat cellFormat2, WritableSheet sheet) throws Exception {
        for (DownloadOrdersDetailVO p : downloadOrdersDetailList) {
            if (!Checker.isNone(p)) {
                String orderNoValue = p.getOrderNo();
                String getChannelValue = (GetChannelEnum.valueOf(p.getGetChannel())).getDisplayName();
                String goodsNameValue = p.getGoodsName();
                String typeNameValue = p.getTypeName();
                String goodsSpecValue = p.getGoodsSpec();
                String goodsPriceValue = FormatUtil.intShrink100ToStr(Checker.getIntegerValue(p.getGoodsPriceInt()));
                String goodsNumberValue = Checker.getIntegerValue(p.getGoodsNumber()) + "";
                String payAmountValue = FormatUtil.intShrink100ToStr(Checker.getIntegerValue(p.getPayAmountInt()));
                String createTimeValue = DateUtil.convertToString(p.getCreateTimeDate());
                String paymentTimeValue = DateUtil.convertToString(p.getPaymentTimeDate());
                String refundTimeValue = DateUtil.convertToString(p.getRefundTimeDate());

                String[] bodyStr = new String[]{orderNoValue, getChannelValue, goodsNameValue, typeNameValue, goodsSpecValue,
                        goodsPriceValue, goodsNumberValue, payAmountValue, createTimeValue, paymentTimeValue, refundTimeValue};
                ExcelHelper.settingMainBodyLabelCell(sheet, cellFormat2, n, bodyStr);
                n++;
            }
        }

        // 汇总
        n++;
        String[] bodyStr = new String[]{"汇总"};
        ExcelHelper.settingMainBodyLabelCell(sheet, cellFormat2, n, bodyStr);
        n++;

        String[] secondTitleStr = new String[]{"名称", "规格", "单价", "数量", "总价"};
        // 第二行格式
        ExcelHelper.settingMainBodyLabelCell(sheet, cellFormat2, n, secondTitleStr);
        List<DownloadOrdersDetailVO> newList = new ArrayList<>();
        for (DownloadOrdersDetailVO vo : downloadOrdersDetailList) {
            vo.setGroupBy(vo.getGoodsId() + "_" + vo.getGoodsPriceInt());
            newList.add(vo);
        }
        // 对新的 list 进行分组
        Map<String, List<DownloadOrdersDetailVO>> detailMap = newList.stream().collect(Collectors.groupingBy(DownloadOrdersDetailVO::getGroupBy));
        // 进行遍历
        int allGoodsNumberValue = 0, allPayAmountInt = 0;
        for (String key : detailMap.keySet()) {
            List<DownloadOrdersDetailVO> valueListVo = detailMap.get(key);
            if (!Checker.isNone(valueListVo)) {
                String goodsNameValue = valueListVo.get(0).getGoodsName();
                String goodsSpecValue = valueListVo.get(0).getGoodsSpec();
                String goodsPriceValue = FormatUtil.intShrink100ToStr(valueListVo.get(0).getGoodsPriceInt());
                int goodsNumberValue = valueListVo.stream().mapToInt(DownloadOrdersDetailVO::getGoodsNumber).sum();
                int payAmountInt = valueListVo.stream().mapToInt(DownloadOrdersDetailVO::getPayAmountInt).sum();
                String payAmountValue = FormatUtil.intShrink100ToStr(payAmountInt);

                String[] secondBodyStr = new String[]{goodsNameValue, goodsSpecValue, goodsPriceValue, goodsNumberValue + "", payAmountValue};
                ExcelHelper.settingMainBodyLabelCell(sheet, cellFormat2, n, secondBodyStr);

                allGoodsNumberValue += goodsNumberValue;
                allPayAmountInt += payAmountInt;
                n++;
            }
        }
        // 汇总
        Label labVal = new Label(0, n, "总计", cellFormat2);
        sheet.addCell(labVal);
        Label labVal1 = new Label(1, n, "", cellFormat2);
        sheet.addCell(labVal1);
        Label labVal2 = new Label(2, n, "", cellFormat2);
        sheet.addCell(labVal2);
        sheet.mergeCells(0, n, 2, n);
        Label allGoodsNumberCel = new Label(3, n, allGoodsNumberValue + "", cellFormat2);
        sheet.addCell(allGoodsNumberCel);
        Label allPayAmountCel = new Label(4, n, FormatUtil.intShrink100ToStr(allPayAmountInt), cellFormat2);
        sheet.addCell(allPayAmountCel);
        n++;
    }

    public DataResponse getGoodsRemark(int orderId, int detailId) {
        DataResponse response = new DataResponse();
        GoodsOrdersDetail detail = goodsOrdersDetailRepository.findByIdAndOrderId(detailId, orderId);
        if (Checker.isNone(detail)) {
            return response.failedWithParameterError("该订单不存在");
        }
        OrderDetailVo vo = new OrderDetailVo();
        vo.setDetailId(detail.getId());
        vo.setOrderId(detail.getGoodsOrdersId());
        vo.setRemark(Checker.getStringValue(detail.getRemark()));
        response.setData(vo);
        response.succeed();
        return response;
    }

    public BaseResponse saveDetailRemark(OrderDetailVo request) {
        BaseResponse response = new BaseResponse();
        GoodsOrdersDetail detail = goodsOrdersDetailRepository.findByIdAndOrderId(request.getDetailId(), request.getOrderId());
        if (Checker.isNone(detail)) {
            return response.failedWithParameterError("该订单不存在");
        }
        detail.setRemark(Checker.getStringValue(request.getRemark()));
        detail.setUpdateTime(new Date());
        goodsOrdersDetailRepository.save(detail);

        return response.succeed();
    }

}
