package cn.ezhizao.project.websocket.service;

import cn.ezhizao.common.utils.uuid.SnowflakeIdWorker;
import cn.ezhizao.project.websocket.WebSocketExport;
import cn.ezhizao.project.websocket.domain.BizProcessInspecion;
import cn.ezhizao.project.websocket.domain.BizProcessInspectionExport;
import cn.ezhizao.project.websocket.mapper.BizProcessInspecionMapper;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson2.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@Service
public class TaskService {
    //    @Resource
//    WebSocketExport webSocketUser;
    @Resource
    BizProcessInspecionMapper bizProcessInspecionMapper;
    @Value("${file.upload.path}")
    private String filePath;
    @Value("${file.upload.url}")
    private String uploadUrl;

    @Resource
    SnowflakeIdWorker snowflakeIdWorker;

    @Async
//    @Log(title = "导出外协审核列表", businessType = BusinessType.EXPORT)
    public void processTaskAsync(BizProcessInspecion bizProcessInspecion, Long userId) {
        try {
            // 获取所有整年的检查的数量
            Long count = bizProcessInspecionMapper.getCountForExport(bizProcessInspecion);
            // 判断行数
            int pageSize = 1000;
            int pageNum = 0;
            int rowIndex = 0;
            ExcelWriter writer = ExcelUtil.getWriter(true);
            // 文件导出位置
            File file = new File(filePath + "/excel");
            JSONObject result = new JSONObject();
            // 判断文件夹是否存在，假设不存在则创建
            if (!file.exists() && !file.isDirectory()) {
                file.mkdir();
            }
            // 分页
            // 循环
            // 存到excel中
//            while(rowIndex < 30000) {
//                pageNum = 0;
            for (; pageNum < (count % 1000 > 0 ? (count / 1000 + 1) : count / 1000); pageNum++) {
                bizProcessInspecion.setStart(pageNum * pageSize);
                bizProcessInspecion.setPageSize(pageSize);
                List<BizProcessInspectionExport> exportList = bizProcessInspecionMapper.getExportList(bizProcessInspecion);
                rowIndex = insertToSheet(writer, rowIndex, exportList);
                // 每页发送消息到前端告知完成状态
                result.put("progress", BigDecimal.valueOf((long) rowIndex - 1).divide(BigDecimal.valueOf(count), 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
                WebSocketExport.sendInfo(result.toJSONString(), String.valueOf(userId));
            }
//            }
            // excel输出到文件夹
            // 完成后保存到本地
            String fileName = String.valueOf(snowflakeIdWorker.nextId());
            FileOutputStream out = new FileOutputStream(file.getAbsolutePath() + "/" + fileName + ".xlsx");
            writer.flush(out);
            writer.close();
            result.put("progress", 100);
            result.put("url", "/profile/upload" + "/excel/" + fileName + ".xlsx");
            WebSocketExport.sendInfo(result.toJSONString(), String.valueOf(userId));
        } catch (Exception e) {
            // 处理错误
            JSONObject err = new JSONObject();
            err.put("err", "保存出错");
            try {
                WebSocketExport.sendInfo(err.toJSONString(), String.valueOf(userId));
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
            throw new RuntimeException("导出错误");
        }
    }

    public Integer insertToSheet(ExcelWriter writer, Integer rowIndex, List<BizProcessInspectionExport> data) {
        if (rowIndex == 0) {
            // 输出第一行表头
            writer.writeCellValue(0, rowIndex, "单位编码");
            writer.writeCellValue(1, rowIndex, "单位简称");
            writer.writeCellValue(2, rowIndex, "产品描述");
            writer.writeCellValue(3, rowIndex, "批号");
            writer.writeCellValue(4, rowIndex, "发出量");
            writer.writeCellValue(5, rowIndex, "投入数量");
            writer.writeCellValue(6, rowIndex, "收回量");
            writer.writeCellValue(7, rowIndex, "料损数量");
            writer.writeCellValue(8, rowIndex, "工序简称");
            writer.writeCellValue(9, rowIndex, "发出日期");
            writer.writeCellValue(10, rowIndex, "收回日期");
            writer.writeCellValue(11, rowIndex, "审核日期");
            writer.writeCellValue(12, rowIndex, "结算日期");
            writer.writeCellValue(13, rowIndex, "发出单号");
            writer.writeCellValue(14, rowIndex, "收回单号");
            writer.writeCellValue(15, rowIndex, "箱数");
            writer.writeCellValue(16, rowIndex, "审核状态");
            return insertToSheet(writer, rowIndex + 1, data);
        } else {
            AtomicInteger i = new AtomicInteger();
            data.forEach(l -> {
                writer.writeCellValue(0, rowIndex + i.get(), l.getMnemonicCode());
                writer.writeCellValue(1, rowIndex + i.get(), l.getSupplierName());
                writer.writeCellValue(2, rowIndex + i.get(), l.getProductDescription());
                writer.writeCellValue(3, rowIndex + i.get(), l.getLotCode());
                writer.writeCellValue(4, rowIndex + i.get(), l.getProductNum());
                writer.writeCellValue(5, rowIndex + i.get(), l.getProductNum());
                writer.writeCellValue(6, rowIndex + i.get(), l.getAuditNum());
                writer.writeCellValue(7, rowIndex + i.get(), l.getMaterialLoss());
                writer.writeCellValue(8, rowIndex + i.get(), l.getProcessAlias());
                writer.writeCellValue(9, rowIndex + i.get(), l.getOutsourceDate());
                writer.writeCellValue(10, rowIndex + i.get(), l.getReturnReceiptDate());
                writer.writeCellValue(11, rowIndex + i.get(), l.getAuditDate());
                writer.writeCellValue(12, rowIndex + i.get(), l.getBalanceDate());
                writer.writeCellValue(13, rowIndex + i.get(), l.getOutsourcedOrderDetailFormCode());
                writer.writeCellValue(14, rowIndex + i.get(), l.getReturnReceiptDetailFormCode());
                writer.writeCellValue(15, rowIndex + i.get(), l.getCarrierNum());
                writer.writeCellValue(16, rowIndex + i.get(), l.getAuditStatus());
                i.getAndIncrement();
            });
            return rowIndex + data.size();
        }
    }
}
