package thyyxxk.webserver.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ReflectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jetbrains.annotations.NotNull;
import thyyxxk.webserver.entity.ComplexSheetData;
import thyyxxk.webserver.entity.HeadInfo;
import thyyxxk.webserver.entity.nationalmatch.SiCentralSuppliesMini;

import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author dj
 */
@Slf4j
public class ExcelUtil {

    public static List<SiCentralSuppliesMini> startRead() {
        Workbook wb;
        Sheet sheet;
        Row row;
        List<SiCentralSuppliesMini> list = new ArrayList<>();
        String filePath = "D:\\副本.xlsx";
        wb = readExcel(filePath);
        if (wb != null) {
            //获取第一个sheet
            sheet = wb.getSheetAt(0);
            //获取最大行数
            int rownum = sheet.getPhysicalNumberOfRows();
            for (int i = 1; i < rownum; i++) {
                row = sheet.getRow(i);
                if (null == row) {
                    break;
                }
                String code = getCellFormatValue(row.getCell(0));
                if (StringUtil.notBlank(code)) {
                    SiCentralSuppliesMini item = new SiCentralSuppliesMini();
                    item.setNationalCode(code);
                    item.setSiName(getCellFormatValue(row.getCell(4)));
                    item.setMaterial(getCellFormatValue(row.getCell(5)));
                    item.setNationalName(getCellFormatValue(row.getCell(8)));
                    item.setFactory(getCellFormatValue(row.getCell(9)));
                    list.add(item);
                }
            }
        }
        return list;
    }


    //读取excel
    public static Workbook readExcel(String filePath) {
        if (filePath == null) {
            return null;
        }
        String extString = filePath.substring(filePath.lastIndexOf("."));
        InputStream is;
        try {
            is = new FileInputStream(filePath);
            if (".xls".equals(extString)) {
                return new HSSFWorkbook(is);
            } else if (".xlsx".equals(extString)) {
                return new XSSFWorkbook(is);
            } else {
                return null;
            }

        } catch (IOException e) {
            log.error("读取EXCEL文件出错", e);
        }
        return null;
    }

    public static String getCellFormatValue(Cell cell) {
        if (cell != null) {
            CellType type = cell.getCellType();
            //判断cell类型
            switch (type) {
                case NUMERIC:
                    return String.valueOf(cell.getNumericCellValue());
                case FORMULA:
                    //判断cell是否为日期格式
                    if (DateUtil.isCellDateFormatted(cell)) {
                        //转换为日期格式YYYY-mm-dd
                        return thyyxxk.webserver.utils.DateUtil.formatDatetime(cell.getDateCellValue(),"yyyy-MM-dd");
                    } else {
                        //数字
                        return String.valueOf(cell.getNumericCellValue());
                    }
                case STRING:
                    return cell.getRichStringCellValue().getString();
                default:
                    return null;
            }
        }
        return null;
    }


    /**
     * 导出Excel
     */
    private static @NotNull HSSFWorkbook getHssfWorkbook(String @NotNull [] title, String[][] values) {
        // 第一步，创建一个HSSFWorkbook，对应一个Excel文件
        HSSFWorkbook wb = new HSSFWorkbook();

        // 第二步，在workbook中添加一个sheet，对应Excel文件中的sheet
        HSSFSheet sheet = wb.createSheet("sheet1");

        // 第三步，在sheet中添加表头第0行，注意老版本poi对Excel行数列数有限制
        HSSFRow row = sheet.createRow(0);

        // 第四步，创建单元格，并设置表头 设置表头居中
        HSSFCellStyle style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);

        // 声明列对象
        HSSFCell cell;

        // 创建标题
        for (int i = 0; i < title.length; i++) {
            cell = row.createCell(i);
            cell.setCellValue(title[i]);
            cell.setCellStyle(style);
        }

        // 创建内容
        for (int i = 0; i < values.length; i++) {
            if (null == values[i]) {
                continue;
            }
            row = sheet.createRow(i + 1);
            for (int j = 0; j < values[i].length; j++) {
                // 将内容按顺序赋给对应的列对象
                row.createCell(j).setCellValue(values[i][j]);
            }
        }
        return wb;
    }

    public static void exportExcel(@NotNull HttpServletResponse response,
                                   String[] title, String[][] values) {
        HSSFWorkbook wb = ExcelUtil.getHssfWorkbook(title, values);
        response.setContentType("application/octet-stream;charset=ISO8859-1");
        response.setHeader("Cache-Control", "no-cache");
        OutputStream out = null;
        try {
            out = response.getOutputStream();
            wb.write(out);
        } catch (Exception e) {
            log.error("导出EXCEL文件出错", e);
        } finally {
            try {
                if (null != out) {
                    out.flush();
                    out.close();
                }
                wb.close();
            } catch (Exception e) {
                log.error("关闭导出EXCEL输出流出错", e);
            }
        }
    }

    /**
     * @description: 后台导出excel
     * @author: hsh
     * @date: 2022/11/4 8:47
     * @param: [response, recordList 导出数据, headList 导出excel表头, report_name 导出excel名称、标题]
     * @return: void
     **/
    public static void exportExcelReport(HttpServletResponse response, List<Map<String, Object>> recordList, List<HeadInfo> headList, String report_name) {
        // Excel数据拼接
        HSSFWorkbook wb = new HSSFWorkbook();

        //设置总列数，下面要用到
        int cellCounts = -1 ;
        int rowIndex = 1;

        boolean isSecondaryMeter = false; // 不存在二级表头

        for (HeadInfo head : headList) {
            if(!"操作".equals(head.getDisplay())){
                if(head.getColumns() != null){
                    List<HeadInfo>  columns = head.getColumns();
                    rowIndex = 2;
                    isSecondaryMeter = true; // 存在二级表头
                    cellCounts+=columns.size();
                }else{
                    cellCounts++;
                }
            }
        }
        // 设置样式
        HSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER); // 创建一个居中格式
        cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
        cellStyle.setBorderLeft(BorderStyle.THIN);//左边框
        cellStyle.setBorderTop(BorderStyle.THIN);//上边框
        cellStyle.setBorderRight(BorderStyle.THIN);//右边框
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

        // 建立新的sheet对象（excel的表单）
        HSSFSheet sheet = wb.createSheet(report_name);
        HSSFRow row1 = sheet.createRow(0);
        // 创建单元格,参数为列的索引
        HSSFCell cell = row1.createCell(0);
        //表头样式
        HSSFCellStyle topicStyle = wb.createCellStyle();
        HSSFFont font =  wb.createFont();//创建字体对象
        font.setFontName("微软雅黑");
        font.setFontHeightInPoints((short)20);
        topicStyle.setFont(font);
        topicStyle.setAlignment(HorizontalAlignment.CENTER);
        topicStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        cell.setCellStyle(topicStyle);// 将样式应用于单元格

        cell.setCellValue(report_name);
        // 合并单元格CellRangeAddress构造参数依次表示起始行，截至行，起始列， 截至列
        CellRangeAddress cra1 = new CellRangeAddress(0, 0, 0, cellCounts);
        sheet.addMergedRegion(cra1);
        createCellRangeBorder(cra1, sheet);

        //创造第二 三行表头
        HSSFRow row2 = sheet.createRow(1);

        HSSFRow row3 = null;
        if(isSecondaryMeter) {
            row3 = sheet.createRow(rowIndex);
        }

        int index = 0 ;
        List<String> keyList = new ArrayList<>();
        for (HeadInfo head : headList) {
            if(!"操作".equals(head.getDisplay())){
                if(head.getColumns() != null){
                    List<HeadInfo>  columns = head.getColumns();
                    CellRangeAddress cra = new CellRangeAddress(1, 1, index, index+columns.size()-1);
                    sheet.addMergedRegion(cra);
                    createCellRangeBorder(cra, sheet);
                    createHeaderInfo(row2,cellStyle,index,head.getDisplay());
                    for (HeadInfo column : columns) {
                        assert row3 != null;
                        createHeader(row3,cellStyle,index,column.getDisplay());
                        keyList.add(column.getName());
                        index++;
                    }
                }else{
                    if(rowIndex>1) {
                        CellRangeAddress cra = new CellRangeAddress(1, rowIndex, index, index);
                        sheet.addMergedRegion(cra);
                        createCellRangeBorder(cra, sheet);
                    }
                    createHeaderInfo(row2,cellStyle,index,head.getDisplay());
                    keyList.add(head.getName());
                    index++;
                }
            }
        }

        int index2 = rowIndex+1;
        for (Map<String, Object> map : recordList) {
            //第二行开始
            HSSFRow row = sheet.createRow(index2);

            for (int i = 0; i < keyList.size(); i++) {
                createHeaderInfo(row,cellStyle,i,(map.get(keyList.get(i))==null?"": map.get(keyList.get(i)) + ""));

            }
            index2++;
        }

        // 处理中文不能自动调整列宽的问题
        for (int i = 0; i < cellCounts+1; i++) {
            // 调整每一列宽度
            sheet.autoSizeColumn((short) i);
            // 解决自动设置列宽中文失效的问题
            int colWidth=sheet.getColumnWidth(i) * 17 / 10;
            // sheet 最大单元格长度问题处理
            if(colWidth<255*256){
                sheet.setColumnWidth(i, sheet.getColumnWidth(i) * 17 / 10);
            }else{
                sheet.setColumnWidth(i,255*256 );
            }
        }

        response.setContentType("application/octet-stream;charset=ISO8859-1");
        response.setHeader("Cache-Control", "no-cache");
        OutputStream out = null;
        try {
            out = response.getOutputStream();
            wb.write(out);
        } catch (Exception e) {
            log.error("导出EXCEL文件出错", e);
        } finally {
            try {
                if (null != out) {
                    out.flush();
                    out.close();
                }
                wb.close();
            } catch (Exception e) {
                log.error("关闭导出EXCEL输出流出错", e);
            }
        }
    }

    // 补全合并单元格格子线条
    public static void createCellRangeBorder(CellRangeAddress cellRange, HSSFSheet sheet) {
        RegionUtil.setBorderBottom(BorderStyle.THIN, cellRange, sheet);
        RegionUtil.setBorderTop(BorderStyle.THIN, cellRange, sheet);
        RegionUtil.setBorderLeft(BorderStyle.THIN, cellRange, sheet);
        RegionUtil.setBorderRight(BorderStyle.THIN, cellRange, sheet);
    }

    private static void createHeader(HSSFRow hfCell1, HSSFCellStyle cellStyle, int column, String value) {
        HSSFCell row = hfCell1.createCell(column);
        // 将样式应用于单元格
        row.setCellStyle(cellStyle);
        if(StringUtil.notBlank(value) && !"null".equals(value)){
            value=processNumer(value);
            row.setCellValue(value);

        } else {
            row.setCellValue(value);
        }
    }

    private static void createHeaderInfo(HSSFRow hfCell1, HSSFCellStyle cellStyle, int column, String value) {
        HSSFCell row = hfCell1.createCell(column);
        // 将样式应用于单元格
        row.setCellStyle(cellStyle);
        if(StringUtil.notBlank(value) && !"null".equals(value)){
            value = processNumer(value);
            row.setCellValue(value);
        } else {
            row.setCellValue(value);
        }
    }

    public static String processNumer(String value){
        // 包含点，并且是整数和.
        String pattren="([0-9]\\d*\\.?\\d*)|((-)?[0-9]\\d*\\.?\\d*)";

        if(value.contains(".") && value.matches(pattren)){
            try{
                BigDecimal bigDecimal=new BigDecimal(value);
                bigDecimal=bigDecimal.setScale(2, RoundingMode.HALF_UP);
                return bigDecimal.toString();
            }catch (Exception e){
                return value;
            }
        }
        return value;
    }

    /**
     * @description:封装导出的表头 displays 和 names 按顺序一一对应,长度必须一样
     * @author: lihong
     * @date: 2023/1/30 10:35
     * @param: displays  字段中文
     * @param: names  字段
     * @return: java.util.List<thyyxxk.webserver.entity.HeadInfo>
     **/
    public static  List<HeadInfo>  createHeadInfos(String[] displays,String[] names){
        List<HeadInfo> headList = new ArrayList<>(displays.length);
        for (int i = 0; i < displays.length; i++) {
            HeadInfo headInfo = new HeadInfo();
            headInfo.setDisplay(displays[i]);
            headInfo.setName(names[i]);
            headList.add(headInfo);
        }
        return headList;
    }
    /**
     * @description:集合bean转为map 格式化时间类型
     * @author: lihong
     * @date: 2023/1/30 10:47
     * @param: list
     * @param: beanClass
     * @return: java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
     **/
    public static<T> List<Map<String,Object>>  beanToMap(List<T> list,Class<?> beanClass){
        List<Map<String, Object>> result = new ArrayList<>();
        list.forEach(bean -> {
            Map<String, Object> temp = BeanUtil.beanToMap(bean);
            Field[] fields = ReflectUtil.getFields(beanClass);
            for (Field field : fields) {
                Object fieldValue = ReflectUtil.getFieldValue(bean, field);
                if(fieldValue instanceof Date){
                    temp.put(ReflectUtil.getFieldName(field),cn.hutool.core.date.DateUtil.formatDateTime((Date)fieldValue));
                }
            }
            result.add(temp);
        });
        return result;
    }

    /**
     * 多Sheet复杂报表导出
     */
    public static void exportMultiSheetReport(HttpServletResponse response,
                                              List<ComplexSheetData> sheetDataList,
                                              String fileName) {
        HSSFWorkbook wb = new HSSFWorkbook();
        try {
            // 遍历每个Sheet配置
            for (ComplexSheetData sheetData : sheetDataList) {
                addComplexSheet(wb, sheetData);
            }

            // 设置响应头
            String encodedFileName = URLEncoder.encode(fileName, "UTF-8");
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + encodedFileName);

            // 写入输出流
            try (OutputStream out = response.getOutputStream()) {
                wb.write(out);
            }
            wb.close();
        } catch (IOException e) {
            log.error("多Sheet导出失败", e);
        }
    }

    /**
     * 添加复杂表头的Sheet
     */
    private static void addComplexSheet(HSSFWorkbook wb, ComplexSheetData sheetData) {
        HSSFSheet sheet = wb.createSheet(sheetData.getSheetName());
        List<HeadInfo> headers = sheetData.getHeaders();
        List<Map<String, Object>> data = sheetData.getData();

        // ============= 表头生成部分 =============
        int cellCounts = -1;
        int rowIndex = 1;
        boolean hasSecondaryHeader = false;

        // 1. 计算列数和表头层级
        for (HeadInfo head : headers) {
            if (head.getColumns() != null) {
                hasSecondaryHeader = true;
                cellCounts += head.getColumns().size();
            } else {
                cellCounts++;
            }
        }

        // 2. 创建样式
        HSSFCellStyle cellStyle = createCommonStyle(wb);
        HSSFCellStyle titleStyle = createTitleStyle(wb);

        // 3. 创建标题行
        HSSFRow titleRow = sheet.createRow(0);
        HSSFCell titleCell = titleRow.createCell(0);
        titleCell.setCellStyle(titleStyle);
        titleCell.setCellValue(sheetData.getSheetName());
        safeAddMergedRegion(sheet, 0, 0, 0, cellCounts); // 合并标题行

        // 4. 创建表头行
        HSSFRow row2 = sheet.createRow(1);
        HSSFRow row3 = hasSecondaryHeader ? sheet.createRow(2) : null;
        int currentCol = 0;
        List<String> columnKeys = new ArrayList<>();

        for (HeadInfo head : headers) {
            if (head.getColumns() != null) {
                // ========== 处理二级表头 ==========
                List<HeadInfo> columns = head.getColumns();
                int mergeCols = columns.size();

                // 合并一级表头单元格（横向合并）
                safeAddMergedRegion(sheet, 1, 1, currentCol, currentCol + mergeCols - 1);
                createHeaderCell(row2, currentCol, head.getDisplay(), cellStyle);

                // 创建二级表头
                for (HeadInfo column : columns) {
                    createHeaderCell(row3, currentCol, column.getDisplay(), cellStyle);
                    columnKeys.add(column.getName());
                    currentCol++;
                }
            } else {
                // ========== 处理单级表头 ==========
                if (hasSecondaryHeader) {
                    // 存在二级表头时，纵向合并到第二行
                    safeAddMergedRegion(sheet, 1, 2, currentCol, currentCol);
                } else {
                    // 无二级表头时不合并
                }
                createHeaderCell(row2, currentCol, head.getDisplay(), cellStyle);
                columnKeys.add(head.getName());
                currentCol++;
            }
        }

        // ============= 数据填充部分 =============
        int dataStartRow = hasSecondaryHeader ? 3 : 2;
        for (int i = 0; i < data.size(); i++) {
            HSSFRow dataRow = sheet.createRow(dataStartRow + i);
            Map<String, Object> record = data.get(i);
            for (int j = 0; j < columnKeys.size(); j++) {
                Object value = record.get(columnKeys.get(j));
                HSSFCell cell = dataRow.createCell(j);
                cell.setCellStyle(cellStyle);
                cell.setCellValue(value != null ? value.toString() : "");
            }
        }

        // ============= 列宽调整 =============
        autoSizeColumns(sheet, columnKeys.size());
    }

    // 安全合并区域方法（核心修复）
    private static void safeAddMergedRegion(HSSFSheet sheet, int firstRow, int lastRow, int firstCol, int lastCol) {
        // 校验是否为有效合并区域
        if (firstRow > lastRow || firstCol > lastCol) {
            log.warn("无效合并区域: {}-{}, {}-{}", firstRow, lastRow, firstCol, lastCol);
            return;
        }
        // 单单元格区域不合并
        if (firstRow == lastRow && firstCol == lastCol) return;

        CellRangeAddress range = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);
        sheet.addMergedRegion(range);
        setRangeBorder(range, sheet);
    }

    // 自动调整列宽（处理中文）
    private static void autoSizeColumns(HSSFSheet sheet, int columnCount) {
        for (int i = 0; i < columnCount; i++) {
            sheet.autoSizeColumn(i);
            int width = sheet.getColumnWidth(i) * 17 / 10;
            sheet.setColumnWidth(i, Math.min(width, 255 * 256));
        }
    }

    private static HSSFCellStyle createCommonStyle(HSSFWorkbook wb) {
        HSSFCellStyle style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        return style;
    }

    private static HSSFCellStyle createTitleStyle(HSSFWorkbook wb) {
        HSSFCellStyle style = wb.createCellStyle();
        HSSFFont font = wb.createFont();
        font.setFontName("微软雅黑");
        font.setFontHeightInPoints((short)16);
        font.setBold(true);
        style.setFont(font);
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        return style;
    }

    private static void createHeaderCell(HSSFRow row, int col, String value, HSSFCellStyle style) {
        HSSFCell cell = row.createCell(col);
        cell.setCellStyle(style);
        cell.setCellValue(value);
    }

    private static void setRangeBorder(CellRangeAddress range, HSSFSheet sheet) {
        RegionUtil.setBorderTop(BorderStyle.THIN, range, sheet);
        RegionUtil.setBorderBottom(BorderStyle.THIN, range, sheet);
        RegionUtil.setBorderLeft(BorderStyle.THIN, range, sheet);
        RegionUtil.setBorderRight(BorderStyle.THIN, range, sheet);
    }
}
