package com.ruoyi.common.utils.poi;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import cn.afterturn.easypoi.handler.inter.IExcelModel;
import cn.afterturn.easypoi.handler.inter.IExcelVerifyHandler;
import cn.hutool.core.util.ObjectUtil;
import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.apache.poi.ss.usermodel.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;

public class ImportUtil {

    /**
     * 导入excel
     *
     * @param titleRows          标题行数
     * @param headRows           头行数
     * @param clazz              数据类型
     * @param verifyHandler      校验
     * @param multipartFile      文件
     * @param isVerifyFailReturn 错误是否返回
     * @return
     * @throws Exception
     */
    public static Map<String, Object> importExcel(Integer titleRows, Integer headRows, Class<? extends IExcelModel> clazz,
                                                  IExcelVerifyHandler<? extends IExcelModel> verifyHandler,
                                                  MultipartFile multipartFile, boolean isVerifyFailReturn) throws Exception {
        Map<String, Object> map = new HashMap<>();
        ExcelImportResult<IExcelModel> result = null;

        ImportParams params = new ImportParams();
        params.setTitleRows(titleRows);
        params.setHeadRows(headRows);
        // 开启Excel校验
        params.setNeedVerify(true);
        params.setVerifyHandler(verifyHandler);
        result = ExcelImportUtil.importExcelMore(multipartFile.getInputStream(), clazz, params);

        System.out.println("是否校验失败: " + result.isVerifyFail());

        List<String> failList = new ArrayList<>();
        if (result.isVerifyFail()) {
            for (IExcelModel o : result.getFailList()) {
                failList.add(o.getErrorMsg());
            }
            map.put("status", false);
            map.put("fail", failList);
            if (isVerifyFailReturn) {
                return map;
            }
        } else {
            map.put("status", true);
        }

        // 验证后不重复，有效的数据
        List<IExcelModel> list = result.getList();
        map.put("success", list);
        return map;
    }

    /**
     * 导入excel
     *
     * @param titleRows          标题行数
     * @param headRows           头行数
     * @param clazz              数据类型
     * @param multipartFile      文件
     * @return
     * @throws Exception
     */
    public static Map<String, Object> importExcel(Integer titleRows, Integer headRows, Class<? extends IExcelModel> clazz,
                                                  MultipartFile multipartFile) throws Exception {
        Map<String, Object> map = new HashMap<>();

        ImportParams params = new ImportParams();
        params.setTitleRows(titleRows);
        params.setHeadRows(headRows);
        // Excel校验
        params.setNeedVerify(false);
        // 并行
        params.setConcurrentTask(true);

        ExcelImportResult<IExcelModel> result = ExcelImportUtil.importExcelMore(multipartFile.getInputStream(), clazz, params);
        map.put("success", result.getList());
        return map;
    }

    /**
     * 读取单sheet数据
     * @param file
     * @param rowIndex 起始行
     * @return
     */
    public static List<Map<Integer, String>> readExcelOneSheet(MultipartFile file, String sheetName, int rowIndex) {
        //创建工作簿
        Workbook workbook = null;
        try {
            ZipSecureFile.setMinInflateRatio(-1.0d);
            workbook = WorkbookFactory.create(file.getInputStream());
            Sheet sheet = workbook.getSheet(sheetName);
            if(ObjectUtil.isNull(sheet)){
                return null;
            }
            return readExcel(sheet, rowIndex);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (workbook != null) {
                    workbook.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return new ArrayList<>();
    }

    /**
     * 读取单sheet数据
     * @param file
     * @param rowIndex 起始行
     * @return
     */
    public static List<Map<Integer, String>> readExcelOneSheet(MultipartFile file, int rowIndex) {
        //创建工作簿
        Workbook workbook = null;
        try {
            ZipSecureFile.setMinInflateRatio(-1.0d);
            workbook = WorkbookFactory.create(file.getInputStream());
            Sheet sheet = workbook.getSheetAt(0);

            return readExcel(sheet, rowIndex);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (workbook != null) {
                    workbook.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return new ArrayList<>();
    }

    /**
     * 读取单sheet数据（未进入详评表专用，他们给的导入模版中存在隐藏的sheet）
     * @param file
     * @param rowIndex 起始行
     * @return
     */
    public static List<Map<Integer, String>> readExcelOneSheetForReject(MultipartFile file, int rowIndex) {
        //创建工作簿
        Workbook workbook = null;
        try {
            System.out.println(" ----------> 文件名：" + file.getOriginalFilename());
            ZipSecureFile.setMinInflateRatio(-1.0d);
            workbook = WorkbookFactory.create(file.getInputStream());
            int sheetNum = workbook.getNumberOfSheets();
            System.out.println(" ----------> Sheet个数：" + sheetNum);

            if (sheetNum <= 0) {
                return null;
            } else if(sheetNum == 1){
                Sheet sheet = workbook.getSheetAt(0);
                return readExcel(sheet, rowIndex);
            } else {
                for (int i = 0; i < sheetNum; i++) {
                    Sheet sheet = workbook.getSheetAt(i);
                    int lastRowNum = sheet.getLastRowNum();
                    if(lastRowNum > rowIndex){
                        return readExcel(sheet, rowIndex);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (workbook != null) {
                    workbook.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return new ArrayList<>();
    }

    /**
     * 读取多sheet数据
     * @param file
     * @param rowIndex 起始行
     * @return
     */
    public static Map<String, List<Map<Integer, String>>> readExcelSheets(MultipartFile file, int rowIndex) {
        //存储excel所有sheet信息
        Map<String, List<Map<Integer, String>>> result = new HashMap<>();
        //获取文件流
        //创建工作簿
        Workbook workbook = null;
        try {
            ZipSecureFile.setMinInflateRatio(-1.0d);
            workbook = WorkbookFactory.create(file.getInputStream());
            //获取sheet数量
            int sheetMax = workbook.getNumberOfSheets();
            for (int sheetIndex = 0; sheetIndex < sheetMax; sheetIndex++) {

                Sheet sheet = workbook.getSheetAt(sheetIndex);

                String sheetName = sheet.getSheetName();
                List<Map<Integer, String>> valueList = readExcel(sheet, rowIndex);

                result.put(sheetName, valueList);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (workbook != null) {
                    workbook.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    public static List<Map<Integer, String>> readExcel(Sheet sheet, int rowIndex) {
        List<Map<Integer, String>> valueList = new ArrayList<>();

        //读取行
        int rowMax = sheet.getLastRowNum();
        for (int rowNum = rowIndex; rowNum <= rowMax; rowNum++) {
            Row rowData = sheet.getRow(rowNum);
            if(rowData == null){
                continue;
            }
            Map<Integer, String> valueMap = new LinkedHashMap<>();
            //读取列
            int cellMax = rowData.getLastCellNum();
            for (int cellNum = 0; cellNum < cellMax; cellNum++) {
                Cell cell = rowData.getCell(cellNum);
                if (cell == null) {
                    continue;
                }

                valueMap.put(cellNum, readCell(cell));
            }
            valueList.add(valueMap);
        }
        return valueList;
    }

    public static String readCell(Cell cell){
        String cellValue = "";
        //匹配数据类型
        if (cell.getCellTypeEnum() == CellType.STRING) {
            cellValue = cell.getStringCellValue();
        }

        if (cell.getCellTypeEnum() == CellType.NUMERIC) {
            //数值型
            //poi读取整数会自动转化成小数，这里对整数进行还原，小数不做处理
            long longValue = Math.round(cell.getNumericCellValue());
            if (Double.parseDouble(longValue + ".0") == cell.getNumericCellValue()) {
                cellValue = String.valueOf(longValue);
            } else {
                cellValue = String.valueOf(cell.getNumericCellValue());
            }
        } else if (cell.getCellTypeEnum() == CellType.FORMULA) {
            //公式型
            //公式计算的值不会转化成小数，这里数值获取失败后会获取字符
            try {
                cellValue = String.valueOf(cell.getNumericCellValue());
            } catch (Exception e) {
                cellValue = cell.getStringCellValue();
            }
        }
        return cellValue;
    }

    /**
     * 获取指定行指定列的数据
     * @param file
     * @param rowIndex
     * @param cellIndex
     * @return
     * @throws IOException
     */
    public static String getExcelData(MultipartFile file, int rowIndex, int cellIndex) {
        String result = "";

        Workbook workbook = null;
        try {
            workbook = WorkbookFactory.create(file.getInputStream());
            if (workbook != null) {
                //获取第一张sheet工作表
                Sheet sheet = workbook.getSheetAt(0);
                if (sheet == null) {
                    return result;
                }

                Row row = sheet.getRow(rowIndex);
                if (null == row) {
                    return result;
                }

                Cell cell = row.getCell(cellIndex);
                if(null == cell) {
                    return "";
                }
                result = readCell(cell);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (workbook != null) {
                    workbook.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

}
