package com.wms_main.excel.easypoi.service.base.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wms_main.constant.enums.wms.WmsTaskTypeEnums;
import com.wms_main.dao.ITAppGoodsService;
import com.wms_main.dao.ITAppStockService;
import com.wms_main.dao.ITAppStockUpdateService;
import com.wms_main.dao.ITAppTaskBakService;
import com.wms_main.excel.easypoi.excelTemplate.GoodsExcelTemplate;
import com.wms_main.excel.easypoi.excelTemplate.StockExcelTemplate;
import com.wms_main.excel.easypoi.excelTemplate.StockUpdateExcelTemplate;
import com.wms_main.excel.easypoi.excelTemplate.TaskRecordExcelTemplate;
import com.wms_main.excel.easypoi.service.base.IBaseExportExcelEasyPoi;
import com.wms_main.model.dto.query.GoodsQuery;
import com.wms_main.model.dto.query.StockQuery;
import com.wms_main.model.dto.query.StockUpdateQuery;
import com.wms_main.model.dto.query.WmsTaskQuery;
import com.wms_main.model.po.TAppGoods;
import com.wms_main.model.po.TAppStock;
import com.wms_main.model.po.TAppStockUpdate;
import com.wms_main.model.po.TAppTaskBak;
import com.wms_main.repository.utils.StringUtils;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * 基础导出服务实现
 */
@Slf4j
public class BaseExportExcelEasyPoi implements IBaseExportExcelEasyPoi {
    @Autowired
    protected ITAppStockService appStockService;// 库存服务
    @Autowired
    protected ITAppStockUpdateService appStockUpdateService;// 库存更新服务
    @Autowired
    protected ITAppGoodsService appGoodsService;// 物料服务
    @Autowired
    protected ITAppTaskBakService appTaskBakService;// 任务记录服务

    public BaseExportExcelEasyPoi() {

    }

    /**
     * 实现 导出库存
     * @param stockQuery 查询条件
     * @param response 响应
     * @throws IOException 异常
     */
    @Override
    public void doExportStocks(StockQuery stockQuery, HttpServletResponse response) throws IOException {
        if (stockQuery == null) {
            throw new IOException("参数不能为NULL");
        }
        // 库存查询参数
        LambdaQueryWrapper<TAppStock> lambdaQueryWrapper = new LambdaQueryWrapper<TAppStock>()
                .like(StringUtils.isNotEmpty(stockQuery.getVehicleId()), TAppStock::getVehicleId, stockQuery.getVehicleId())
                .like(StringUtils.isNotEmpty(stockQuery.getLocationId()), TAppStock::getLocationId, stockQuery.getLocationId())
                .like(StringUtils.isNotEmpty(stockQuery.getGoodsId()), TAppStock::getGoodsId, stockQuery.getGoodsId())
                .eq(stockQuery.getStockStatus() != null, TAppStock::getStockStatus, stockQuery.getStockStatus())
                .eq(stockQuery.getGoodsStatus() != null, TAppStock::getGoodsStatus, stockQuery.getGoodsStatus());
        if (stockQuery.getFromDate() != null) {
            lambdaQueryWrapper.ge(TAppStock::getFirstInTime, stockQuery.getFromDate().atStartOfDay());
        }
        if (stockQuery.getToDate() != null) {
            // toDate + 1天的凌晨。
            lambdaQueryWrapper.lt(TAppStock::getFirstInTime, stockQuery.getToDate().plusDays(1).atStartOfDay());
        }
        List<TAppStock> stockList = appStockService.list(lambdaQueryWrapper);
        // excel模版列表
        List<StockExcelTemplate> resultList = new ArrayList<>();
        if (!stockList.isEmpty()) {
            for (TAppStock poData : stockList) {
                resultList.add(new StockExcelTemplate(
                        poData.getStockId(),
                        poData.getVehicleId(),
                        poData.getLocationId(),
                        poData.getStockStatus(),
                        poData.getGoodsId(),
                        poData.getGoodsStatus(),
                        poData.getFirstInTime(),
                        poData.getFirstInUser(),
                        poData.getLastUpdateTime(),
                        poData.getLastUpdateUser(),
                        poData.getTotalNum(),
                        poData.getRemainNum(),
                        poData.getRealNum(),
                        poData.getGoodsDesc(),
                        poData.getExpireDate(),
                        poData.getSled()
                ));
            }
        } else {
            resultList.add(new StockExcelTemplate());
        }
        doWriteExcel("库存", response, resultList, StockExcelTemplate.class);
    }

    /**
     * 导出库存更新记录
     * @param stockUpdateQuery 查询条件
     * @param response 响应
     * @throws IOException 异常
     */
    @Override
    public void doExportStockUpdate(StockUpdateQuery stockUpdateQuery, HttpServletResponse response) throws IOException {
        if (stockUpdateQuery == null) {
            throw new IOException("查询参数不能为NULL");
        }
        // 查询参数
        if (stockUpdateQuery.getFromTime() != null && stockUpdateQuery.getToTime() != null) {
            if (stockUpdateQuery.getFromTime().isAfter(stockUpdateQuery.getToTime())) {
                throw new IOException("from时间不能晚于to时间");
            }
        }
        // 库存更新记录查询参数
        LambdaQueryWrapper<TAppStockUpdate> lambdaQueryWrapper = new LambdaQueryWrapper<TAppStockUpdate>()
                .like(StringUtils.isNotEmpty(stockUpdateQuery.getGoodsId()), TAppStockUpdate::getGoodsId, stockUpdateQuery.getGoodsId())
                .like(StringUtils.isNotEmpty(stockUpdateQuery.getVehicleId()), TAppStockUpdate::getVehicleId, stockUpdateQuery.getVehicleId());
        if (stockUpdateQuery.getFromTime() != null) {
            lambdaQueryWrapper.ge(TAppStockUpdate::getUpdateTime, stockUpdateQuery.getFromTime());
        }
        if (stockUpdateQuery.getToTime() != null) {
            lambdaQueryWrapper.le(TAppStockUpdate::getUpdateTime, stockUpdateQuery.getToTime());
        }
        List<TAppStockUpdate> stockUpdateList = appStockUpdateService.list(lambdaQueryWrapper);
        // excel模版列表
        List<StockUpdateExcelTemplate> resultList = new ArrayList<>();
        if (!stockUpdateList.isEmpty()) {
            for (TAppStockUpdate poData : stockUpdateList) {
                resultList.add(new StockUpdateExcelTemplate(
                        poData.getUpdateId(),
                        poData.getVehicleId(),
                        poData.getGoodsId(),
                        poData.getFirstInTime(),
                        poData.getBeforeNum(),
                        poData.getAfterNum(),
                        poData.getReason(),
                        poData.getUpdateTime(),
                        poData.getUpdateUser()
                ));
            }
        } else {
            resultList.add(new StockUpdateExcelTemplate());
        }
        doWriteExcel("库存更新记录", response, resultList, StockUpdateExcelTemplate.class);
    }

    /**
     * 导出物料信息--实现
     * @param goodsQuery 查询
     */
    @Override
    public void doExportGoods(GoodsQuery goodsQuery, HttpServletResponse response) throws IOException {
        if (goodsQuery == null) {
            throw new IOException("查询参数不能为NULL");
        }
        // 查询参数
        LambdaQueryWrapper<TAppGoods> lambdaQueryWrapper = new LambdaQueryWrapper<TAppGoods>()
                .like(StringUtils.isNotEmpty(goodsQuery.getGoodsId()), TAppGoods::getGoodsId, goodsQuery.getGoodsId())
                .like(StringUtils.isNotEmpty(goodsQuery.getGoodsDesc()), TAppGoods::getGoodsDescription, goodsQuery.getGoodsDesc());
        List<TAppGoods> baseGoodsList = appGoodsService.list(lambdaQueryWrapper);
        // excel模版列表
        List<GoodsExcelTemplate> resultList = new ArrayList<>();
        if (!baseGoodsList.isEmpty()) {
            for (TAppGoods poData : baseGoodsList) {
                resultList.add(new GoodsExcelTemplate(
                        poData.getPlant(),
                        poData.getGoodsId(),
                        poData.getGoodsDescription(),
                        poData.getVendorName(),
                        poData.getFeedingType(),
                        poData.getMaxBoxNum(),
                        poData.getBoxQty(),
                        poData.getHotPoint(),
                        poData.getPutArea(),
                        poData.getIsSled(),
                        poData.getSledDays()
                ));
            }
        } else {
            resultList.add(new GoodsExcelTemplate());
        }
        doWriteExcel("物料基础信息", response, resultList, GoodsExcelTemplate.class);
    }

    /**
     * 导出入库记录
     * @param wmsTaskQuery 查询
     * @param response 响应
     * @throws IOException 异常
     */
    @Override
    public void doExportInTaskRecords(WmsTaskQuery wmsTaskQuery, HttpServletResponse response) throws IOException {
        if (wmsTaskQuery == null) {
            throw new IOException("查询参数不能为NULL");
        }
        // 查询参数
        if (wmsTaskQuery.getFromTime() != null && wmsTaskQuery.getToTime() != null) {
            if (wmsTaskQuery.getFromTime().isAfter(wmsTaskQuery.getToTime())) {
                throw new IOException("from时间不能晚于to时间");
            }
        }
        LambdaQueryWrapper<TAppTaskBak> lambdaQueryWrapper = new LambdaQueryWrapper<TAppTaskBak>()
                .like(StringUtils.isNotEmpty(wmsTaskQuery.getTaskId()), TAppTaskBak::getTaskId, wmsTaskQuery.getTaskId())
                .like(StringUtils.isNotEmpty(wmsTaskQuery.getGoodsId()), TAppTaskBak::getGoodsId, wmsTaskQuery.getGoodsId())
                .like(StringUtils.isNotEmpty(wmsTaskQuery.getVehicleId()), TAppTaskBak::getVehicleId, wmsTaskQuery.getVehicleId())
                .eq(TAppTaskBak::getTaskType, WmsTaskTypeEnums.IN.getCode());
        if (wmsTaskQuery.getFromTime() != null) {
            lambdaQueryWrapper.ge(TAppTaskBak::getCreateTime, wmsTaskQuery.getFromTime());
        }
        if (wmsTaskQuery.getToTime() != null) {
            lambdaQueryWrapper.le(TAppTaskBak::getCreateTime, wmsTaskQuery.getToTime());
        }
        List<TAppTaskBak> inTaskRecordList = appTaskBakService.list(lambdaQueryWrapper);
        // excel模版列表
        List<TaskRecordExcelTemplate> resultList = new ArrayList<>();
        if (!inTaskRecordList.isEmpty()) {
            for (TAppTaskBak poData : inTaskRecordList) {
                resultList.add(new TaskRecordExcelTemplate(
                        poData.getTaskId(),
                        poData.getTaskType(),
                        poData.getTaskStatus(),
                        poData.getTaskPriority(),
                        poData.getVehicleId(),
                        poData.getOrigin(),
                        poData.getDestination(),
                        poData.getWcsTaskId(),
                        poData.getCreateTime(),
                        poData.getFinishTime(),
                        poData.getGoodsId(),
                        poData.getOpNum(),
                        poData.getStockNum(),
                        poData.getOpUser(),
                        poData.getRemark(),
                        poData.getCallStand(),
                        poData.getGoodsDesc()
                ));
            }
        } else {
            resultList.add(new TaskRecordExcelTemplate());
        }
        doWriteExcel("入库记录", response, resultList, TaskRecordExcelTemplate.class);
    }

    /**
     * 导出出库任务记录--实现
     * @param wmsTaskQuery 查询
     * @param response 响应
     * @throws IOException 异常
     */
    @Override
    public void doExportOutTaskRecords(WmsTaskQuery wmsTaskQuery, HttpServletResponse response) throws IOException {
        if (wmsTaskQuery == null) {
            throw new IOException("查询参数不能为NULL");
        }
        // 查询参数
        if (wmsTaskQuery.getFromTime() != null && wmsTaskQuery.getToTime() != null) {
            if (wmsTaskQuery.getFromTime().isAfter(wmsTaskQuery.getToTime())) {
                throw new IOException("from时间不能晚于to时间");
            }
        }
        LambdaQueryWrapper<TAppTaskBak> lambdaQueryWrapper = new LambdaQueryWrapper<TAppTaskBak>()
                .like(StringUtils.isNotEmpty(wmsTaskQuery.getTaskId()), TAppTaskBak::getTaskId, wmsTaskQuery.getTaskId())
                .like(StringUtils.isNotEmpty(wmsTaskQuery.getGoodsId()), TAppTaskBak::getGoodsId, wmsTaskQuery.getGoodsId())
                .like(StringUtils.isNotEmpty(wmsTaskQuery.getVehicleId()), TAppTaskBak::getVehicleId, wmsTaskQuery.getVehicleId())
                .eq(TAppTaskBak::getTaskType, WmsTaskTypeEnums.OUT.getCode());
        if (wmsTaskQuery.getFromTime() != null) {
            lambdaQueryWrapper.ge(TAppTaskBak::getCreateTime, wmsTaskQuery.getFromTime());
        }
        if (wmsTaskQuery.getToTime() != null) {
            lambdaQueryWrapper.le(TAppTaskBak::getCreateTime, wmsTaskQuery.getToTime());
        }
        List<TAppTaskBak> outTaskRecordList = appTaskBakService.list(lambdaQueryWrapper);
        // excel模版列表
        List<TaskRecordExcelTemplate> resultList = new ArrayList<>();
        if (!outTaskRecordList.isEmpty()) {
            for (TAppTaskBak poData : outTaskRecordList) {
                resultList.add(new TaskRecordExcelTemplate(
                        poData.getTaskId(),
                        poData.getTaskType(),
                        poData.getTaskStatus(),
                        poData.getTaskPriority(),
                        poData.getVehicleId(),
                        poData.getOrigin(),
                        poData.getDestination(),
                        poData.getWcsTaskId(),
                        poData.getCreateTime(),
                        poData.getFinishTime(),
                        poData.getGoodsId(),
                        poData.getOpNum(),
                        poData.getStockNum(),
                        poData.getOpUser(),
                        poData.getRemark(),
                        poData.getCallStand(),
                        poData.getGoodsDesc()
                ));
            }
        } else {
            resultList.add(new TaskRecordExcelTemplate());
        }
        doWriteExcel("出库记录", response, resultList, TaskRecordExcelTemplate.class);
    }

    /**
     * 写入excel
     * @param fileDesc 文件描述
     * @param response 响应
     * @param list 数据列表
     * @param clazz 泛型类
     * @param <T> 泛型
     * @throws IOException 异常
     */
    public <T> void doWriteExcel(String fileDesc, HttpServletResponse response, List<T> list, Class<T> clazz) throws IOException {
        ExportParams exportParams = new ExportParams();
        exportParams.setSheetName(fileDesc);
        exportParams.setType(ExcelType.XSSF);
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, clazz, list);
        setResponseHeaderOfExcel(fileDesc, response);
        workbook.write(response.getOutputStream());
        workbook.close();
    }

    /**
     * 设置统一的excel头部文件
     * @param fileDesc 文件名描述
     * @param response 响应
     */
    public void setResponseHeaderOfExcel(String fileDesc, HttpServletResponse response) {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode(fileDesc, StandardCharsets.UTF_8).replaceAll("\\+", "%20");
        response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
    }
}
