package com.testor.module.duty.util;

import cn.hutool.core.util.StrUtil;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 导⼊包含合并单元格的Excel⽂档
 */
public class PoiExcelUtils {
    /**
     * 读取Excel⽂件⼯作表
     *
     * @param input ⽂件流
     * @param fileName    ⽂件名称
     * @return
     */
    public static Workbook readFile(InputStream input, String fileName) {
        Workbook wb = null;
        //判断是否是excel2007格式
        boolean isE2007 = false;
        if (fileName.endsWith("xlsx")) {
            isE2007 = true;
        }
        try {
            //根据⽂件格式(2003或者2007)来初始化
            if (isE2007) {
                wb = new XSSFWorkbook(input);
            } else {
                wb = new HSSFWorkbook(input);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return wb;
    }

    /**
     * 获取内部内容
     *
     * @param sheet       ⼯作表
     * @param column      有效数据列数
     * @param headerCount 表头⾏数
     * @return
     */
    public static List<Map<Integer, Object>> getBody(Sheet sheet, int column, int headerCount) {
        //总行数
        int count = sheet.getLastRowNum() + 1;
        //sheet中所有合并的单元格信息
        List<CellRangeAddress> cras = getCombineCell(sheet);
        //存储行信息
        List<Map<Integer, Object>> irs = new ArrayList<>();
        //获取图片数据
        Map<String, PictureData> pictureDataMap = getPicturesFromSheet(sheet);

        // 表头行
        outerLoop:
        for (int i = headerCount; i < count; i++) {
            //存储列信息
            Map<Integer, Object> map = new HashMap<>();
            innerLoop:
            for (int x = 0; x < column; x++) {
                // 判断当前单元格是不是合并单元格
                CellRangeAddress range = isMergedRegion(cras, i, x);
                // 如果是合并单元格
                if (null != range) {
                    // 取合并单元格起始行列
                    int firstColumn = range.getFirstColumn();
                    int firstRow = range.getFirstRow();
                    Row row = sheet.getRow(firstRow);
                    map.put(x, getCellValue(row.getCell(firstColumn)));
                } else {
                    // 如果不是合并单元格
                    Row row = sheet.getRow(i);
                    if (row == null) {
                        break outerLoop;
                    }
                    Cell cell = row.getCell(x);
                    // 检查该单元格是否包含图片
                    if (pictureDataMap.containsKey(i + "-" + x)) {
                        PictureData pictureData = pictureDataMap.get(i + "-" + x);
                        map.put(x, pictureData);  // 存储图片
                    } else {
                        map.put(x, getCellValue(cell));
                    }
                }
            }
            irs.add(map);
        }
        // 过滤空行
        irs = deleteEmptyRow(irs, column);
        return irs;
    }

    /**
     * 获取图片数据
     *
     * @param sheet 需要导入的工作表
     * @return 图片数据的Map，key为"row-column"，value为图片的PictureData对象
     */
    public static Map<String, PictureData> getPicturesFromSheet(Sheet sheet) {
        Map<String, PictureData> pictureDataMap = new HashMap<>();

        if (sheet instanceof XSSFSheet) {
            XSSFSheet xssfSheet = (XSSFSheet) sheet;
            XSSFDrawing drawing = xssfSheet.getDrawingPatriarch();
            if (drawing != null) {
                List<XSSFShape> shapes = drawing.getShapes();
                for (XSSFShape shape : shapes) {
                    if (shape instanceof XSSFPicture) {
                        XSSFPicture picture = (XSSFPicture) shape;
                        XSSFPictureData pictureData = picture.getPictureData();
                        XSSFClientAnchor anchor = picture.getPreferredSize();
                        String key = anchor.getRow1() + "-" + anchor.getCol1();
                        pictureDataMap.put(key, pictureData);
                    }
                }
            }
        }
        return pictureDataMap;
    }

    /**
     * 获取sheet中合并的单元格信息，并返回合并的单元格list
     *
     * @param sheet 需要导入的工作表
     * @return List<CellRangeAddress>合并的单元格list
     */
    public static List<CellRangeAddress> getCombineCell(Sheet sheet) {
        List<CellRangeAddress> list = new ArrayList<>();
        //获得一个sheet中合并单元格的数量
        int sheetmergerCount = sheet.getNumMergedRegions();
        //遍历所有的合并单元格
        for (int i = 0; i < sheetmergerCount; i++) {
            //获得合并单元格保存进list中
            CellRangeAddress ca = sheet.getMergedRegion(i);
            list.add(ca);
        }
        return list;
    }

    /**
     * 判断指定的单元格是否是合并单元格
     *
     * @param cras
     * @param row
     * @param column
     * @return
     */
    private static CellRangeAddress isMergedRegion(List<CellRangeAddress> cras, int row, int column) {
        for (CellRangeAddress range : cras) {
            int firstColumn = range.getFirstColumn();
            int lastColumn = range.getLastColumn();
            int firstRow = range.getFirstRow();
            int lastRow = range.getLastRow();
            if (row >= firstRow && row <= lastRow) {
                if (column >= firstColumn && column <= lastColumn) {
                    return range;
                }
            }
        }
        return null;
    }

    /**
     * 获取单元格的值
     *
     * @param cell
     * @return
     */
    public static String getCellValue(Cell cell) {
        String cellValue = "";
        if (cell == null) {
            return cellValue;
        }
        //判断数据的类型
        switch (cell.getCellType()) {
            case Cell.CELL_TYPE_NUMERIC: //数字
                if (HSSFDateUtil.isCellDateFormatted(cell)) {// 处理⽇期格式
                    Date date = cell.getDateCellValue();
                    DateFormat formater = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
                    cellValue = formater.format(date);
                } else if (cell.getCellStyle().getDataFormat() == 0) {//处理数值格式
                    cell.setCellType(Cell.CELL_TYPE_STRING);
                    cellValue = String.valueOf(cell.getRichStringCellValue().getString());
                }else {
                    if (cell.getNumericCellValue() % 1 == 0) {
                        cellValue = String.valueOf((int) cell.getNumericCellValue());
                    } else {
                        cellValue = String.valueOf(cell.getNumericCellValue());
                    }
                }
                break;
            case Cell.CELL_TYPE_STRING: // 字符串
                cellValue = String.valueOf(cell.getStringCellValue());
                break;
            case Cell.CELL_TYPE_BOOLEAN: // Boolean
                cellValue = String.valueOf(cell.getBooleanCellValue());
                break;
            case Cell.CELL_TYPE_FORMULA: // 公式
                cellValue = String.valueOf(cell.getCellFormula());
                break;
            case Cell.CELL_TYPE_BLANK: // 空值
                cellValue = "";
                break;
            case Cell.CELL_TYPE_ERROR: // 故障
                cellValue = "";
                break;
            default: // 未知类型
                cellValue = cell.toString().trim();
                break;
        }
        return cellValue;
    }

    public static int getRowNum(List<CellRangeAddress> listCombineCell, Cell cell, Sheet sheet) {
        int xr = 0;
        int firstC = 0;
        int lastC = 0;
        int firstR = 0;
        int lastR = 0;
        for (CellRangeAddress ca : listCombineCell) {
            //获得合并单元格的起始行, 结束行, 起始列, 结束列
            firstC = ca.getFirstColumn();
            lastC = ca.getLastColumn();
            firstR = ca.getFirstRow();
            lastR = ca.getLastRow();
            if (cell.getRowIndex() >= firstR && cell.getRowIndex() <= lastR) {
                if (cell.getColumnIndex() >= firstC && cell.getColumnIndex() <= lastC) {
                    xr = lastR;
                }
            }

        }
        return xr;

    }

    public static boolean isMergedRegion(Sheet sheet, int row, int column) {
        int sheetMergeCount = sheet.getNumMergedRegions();
        for (int i = 0; i < sheetMergeCount; i++) {
            CellRangeAddress range = sheet.getMergedRegion(i);
            int firstColumn = range.getFirstColumn();
            int lastColumn = range.getLastColumn();
            int firstRow = range.getFirstRow();
            int lastRow = range.getLastRow();
            if (row >= firstRow && row <= lastRow) {
                if (column >= firstColumn && column <= lastColumn) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 删除空行，如果中间出现空行，则空行以下的所有行(数据)都不会进行处理（当作空行）
     * 如果空的列数 == 总列数 则认为 为空行
     * @param dataList
     * @param colNum
     * @return
     */
    public static List<Map<Integer, Object>> deleteEmptyRow(List<Map<Integer, Object>> dataList, int colNum) {

        if(dataList == null || dataList.size() == 0 || colNum < 1) {
            return dataList;
        }
        List<Map<Integer, Object>> finalList = new ArrayList();
        for(Map<Integer, Object> dataMap : dataList) {
            int mapKeyNum =0;
            for (Object value : dataMap.values()) {
                if(value == null || StrUtil.isBlank(value.toString())) {
                    mapKeyNum ++;
                }
            }

            // 如果空的列数 == 总列数 则认为 为空行
            // 则空行以下的所有行(数据)都不会进行处理（当作空行）
            if(mapKeyNum == colNum) {
                return finalList;
            }
            finalList.add(dataMap);
        }
        return finalList;
    }
}

