package com.yc.ship.module.trade.utils.excel;


import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import com.yc.ship.module.trade.controller.admin.order.vo.order.TouristExportVisitorVO;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ExcelStyleHandler implements CellWriteHandler {
    private int templateRowIndex;

    private final Map<Integer, CellStyle> templateStyles = new HashMap<>();

    // 保存模板行的合并信息：列索引 -> [起始列, 结束列]
    private final Map<Integer, int[]> templateMergeInfo = new HashMap<>();

    private boolean templateProcessed = false;

    /** 游客列表数据 */
    private List<TouristExportVisitorVO> visitorList;

    /** 数据起始行索引 */
    private static final int DATA_START_ROW = 8;

    /** 记录已处理的单元格数量 */
    private int processedCellCount = 0;

    /** 总数据行数 */
    private int totalRows = 0;

    private int fileType;

    /** 每行数据列数（根据实际Excel模板列数调整） */
    private static final int TOTAL_COLUMNS = 18;

    private static final int TOTAL_COLUMNS2 = 16;
    /** 是否已经执行过合并 */
    private boolean mergeCompleted = false;

    public ExcelStyleHandler(int templateRowIndex) {
        this.templateRowIndex = templateRowIndex;
    }

    public ExcelStyleHandler(List<TouristExportVisitorVO> visitorList, int fileType) {
        this.visitorList = visitorList;
        this.fileType = fileType;
        this.totalRows = visitorList != null ? visitorList.size() : 0;
    }


    public void afterCellDispose1(CellWriteHandlerContext context) {
        if (Boolean.TRUE.equals(context.getHead())) {
            return;
        }

        Cell cell = context.getCell();
        Row currentRow = cell.getRow();
        int currentRowIndex = currentRow.getRowNum();
        int colIndex = cell.getColumnIndex();
        Sheet sheet = context.getWriteSheetHolder().getSheet();
        Workbook workbook = sheet.getWorkbook();

        // 处理模板行：保存样式和合并信息
        if (currentRowIndex == templateRowIndex) {
            if (!templateProcessed) {
                // 保存样式
                saveTemplateStyles(currentRow, workbook);

                // 保存合并信息
                saveTemplateMergeInfo(sheet);

                templateProcessed = true;
            }
            return;
        }

        // 跳过模板行之前的行
        if (currentRowIndex < templateRowIndex) {
            return;
        }

        // ===== 为所有单元格设置样式（包括合并区域内的）=====
       // CellStyle newStyle = workbook.createCellStyle();

// 应用样式
        if (templateStyles.containsKey(colIndex)) {
            //newStyle.cloneStyleFrom(templateStyles.get(colIndex));

            cell.setCellStyle(templateStyles.get(colIndex));
        }


        // 如果这个列在合并区域内，设置边框
        /*if (templateMergeInfo.containsKey(colIndex)) {
            int[] range = templateMergeInfo.get(colIndex);
            int firstCol = range[0];
            int lastCol = range[1];

            // 根据在合并区域中的位置设置边框
            setMergeCellBorders(newStyle, colIndex, firstCol, lastCol);
        }*/

       // cell.setCellStyle(newStyle);

        // 应用合并（只处理合并区域的第一个列）
        if (templateMergeInfo.containsKey(colIndex)) {
            int[] range = templateMergeInfo.get(colIndex);
            int firstCol = range[0];
            int lastCol = range[1];

            // 只在当前列是合并区域的第一个列时创建合并
            if (colIndex == firstCol) {
                CellRangeAddress cra = new CellRangeAddress(
                        currentRowIndex, currentRowIndex, firstCol, lastCol
                );
                sheet.addMergedRegion(cra);

                // 为合并区域设置完整边框
                setMergeCellBorders(sheet.getColumnStyle(colIndex), colIndex, firstCol, lastCol);

            }

        }




    }


    /**
     * 为合并区域的单元格设置边框
     * @param style 单元格样式
     * @param colIndex 当前列索引
     * @param firstCol 合并区域起始列
     * @param lastCol 合并区域结束列
     */
    private void setMergeCellBorders(CellStyle style,  int colIndex, int firstCol, int lastCol) {
        // 设置所有边框为细线
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);

        // 如果有特殊需求，可以根据位置设置不同边框：
        // - 合并区域的第一个单元格：左、上、下边框
        // - 合并区域的最后一个单元格：右、上、下边框
        // - 中间的单元格：上、下边框
    }

    /**
     * 保存模板行的合并信息
     */
    private void saveTemplateMergeInfo(Sheet sheet) {
        List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();
        for (CellRangeAddress cra : mergedRegions) {
            // 只处理模板行上的横向合并
            if (cra.getFirstRow() == templateRowIndex && cra.getLastRow() == templateRowIndex) {
                int firstCol = cra.getFirstColumn();
                int lastCol = cra.getLastColumn();

                // 记录这个合并区域涉及的所有列
                for (int col = firstCol; col <= lastCol; col++) {
                    templateMergeInfo.put(col, new int[]{firstCol, lastCol});
                }
            }
        }
    }

    private void saveTemplateStyles(Row templateRow, Workbook workbook) {
        for (Cell cell : templateRow) {
            if (cell != null && cell.getCellStyle() != null) {
                CellStyle newStyle = workbook.createCellStyle();
                newStyle.cloneStyleFrom(cell.getCellStyle());
                templateStyles.put(cell.getColumnIndex(), newStyle);
            }
        }
    }

    /**
     * 单元格写入完成后执行合并
     * 此方法在每个单元格写入完成后检查是否是最后一个单元格，如果是则统一处理合并
     *
     * @param context 单元格写入上下文
     */
    @Override
    public void afterCellDispose(CellWriteHandlerContext context) {
        // 只处理游客列表场景
        if (visitorList == null || visitorList.isEmpty()) {
            return;
        }

        // 跳过表头行
        if (Boolean.TRUE.equals(context.getHead())) {
            return;
        }

        // 统计处理的单元格数量
        processedCellCount++;

        int totalCells = 0;
        // 当最后一个单元格写入完成后，执行合并
        if(fileType == 1) {
             totalCells = totalRows * TOTAL_COLUMNS;

        } else {
             totalCells = totalRows * TOTAL_COLUMNS2;
        }
        if (!mergeCompleted && processedCellCount >= totalCells) {
            mergeCompleted = true;
            performMerge(context.getWriteSheetHolder().getSheet());
        }
    }

    /**
     * 执行合并操作
     * 此方法在数据写入完成后统一处理合并，避免逐行合并时的磁盘刷新问题
     *
     * 合并规则：
     * 1. 第0列（代理商）：按 sourceName 合并
     * 2. 第1-7列（订单信息）：按 orderNo 合并
     * 3. 第8-10列（房间信息）：按 roomIndexId 合并（同一订单内）
     * 4. 横向不需要合并（按列单独合并）
     *
     * @param sheet Excel工作表
     */
    private void performMerge(Sheet sheet) {
        // 遍历游客列表，从第二行开始与上一行比较
        for (int i = 1; i < visitorList.size(); i++) {
            TouristExportVisitorVO currentVisitor = visitorList.get(i);
            TouristExportVisitorVO preVisitor = visitorList.get(i - 1);

            int currentRowIndex = DATA_START_ROW + i;
            int preRowIndex = DATA_START_ROW + i - 1;

            // ===== 第0列（代理商）：按 sourceName 合并 =====
            if (currentVisitor.getSourceName() != null && preVisitor.getSourceName() != null
                    && currentVisitor.getSourceName().equals(preVisitor.getSourceName())) {
                mergeCell(sheet, currentRowIndex, preRowIndex, 1, 1);
            }

            // ===== 第1-7列（订单信息）：按 orderNo 合并 =====
            // 同一订单的所有游客合并显示订单信息
            if (currentVisitor.getOrderNo() != null
                    && currentVisitor.getOrderNo().equals(preVisitor.getOrderNo())) {
                // 订单号列（第1列）
                mergeCell(sheet, currentRowIndex, preRowIndex, 2, 2);
                // 团号列（第2列）
                mergeCell(sheet, currentRowIndex, preRowIndex, 3, 3);
                // 航向列（第3列）
                mergeCell(sheet, currentRowIndex, preRowIndex, 4, 4);
                // 航期列（第4列）
                mergeCell(sheet, currentRowIndex, preRowIndex, 5, 5);
                // 应收款列（第5列）
                mergeCell(sheet, currentRowIndex, preRowIndex, 6, 6);
                if (fileType == 1) {
                    // 实收款列（第6列）
                    mergeCell(sheet, currentRowIndex, preRowIndex, 7, 7);
                    // 定金列（第7列）
                    mergeCell(sheet, currentRowIndex, preRowIndex, 8, 8);
                }
            }

            // ===== 第8-10列（房间信息）：按 roomIndexId 合并（同一订单内） =====
            String currentRoomIndex = currentVisitor.getRoomIndexId() != null ? currentVisitor.getRoomIndexId() : "";
            String preRoomIndex = preVisitor.getRoomIndexId() != null ? preVisitor.getRoomIndexId() : "";
            if (currentRoomIndex.equals(preRoomIndex)
                    && currentVisitor.getOrderNo() != null
                    && currentVisitor.getOrderNo().equals(preVisitor.getOrderNo())) {
                if (fileType == 1) {
                    // 序号列（第8列）
                    mergeCell(sheet, currentRowIndex, preRowIndex, 9, 9);
                    // 房型列（第9列）
                    mergeCell(sheet, currentRowIndex, preRowIndex, 10, 10);
                    // 入住类型列（第10列）
                    mergeCell(sheet, currentRowIndex, preRowIndex, 11, 11);
                } else {
                    mergeCell(sheet, currentRowIndex, preRowIndex, 7, 7);
                    // 房型列（第9列）
                    mergeCell(sheet, currentRowIndex, preRowIndex, 8, 8);
                    // 入住类型列（第10列）
                    mergeCell(sheet, currentRowIndex, preRowIndex, 9, 9);
                }
            }
        }
    }

    /**
     * 合并单元格并设置边框
     *
     * 功能说明：
     * - 如果目标单元格已存在合并区域，则扩展合并区域
     * - 如果目标单元格未合并，则创建新的合并区域
     * - 设置合并单元格的边框样式
     *
     * @param sheet Excel工作表
     * @param currentRow 当前行索引
     * @param preRow 上一行索引
     * @param startCol 起始列索引
     * @param endCol 结束列索引
     */
    private void mergeCell(Sheet sheet, int currentRow, int preRow, int startCol, int endCol) {
        List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();

        // 检查上一行是否已存在合并区域
        for (int i = 0; i < mergedRegions.size(); i++) {
            CellRangeAddress region = mergedRegions.get(i);
            // 如果合并区域包含上一行的指定列
            if (region.getFirstRow() <= preRow && region.getLastRow() >= preRow
                    && region.getFirstColumn() == startCol && region.getLastColumn() == endCol) {
                // 扩展合并区域
                sheet.removeMergedRegion(i);
                CellRangeAddress newRegion = new CellRangeAddress(region.getFirstRow(), currentRow, startCol, endCol);
                sheet.addMergedRegion(newRegion);
                // setBorder(newRegion, sheet);
                return;
            }
        }

        // 如果没有找到已存在的合并区域，创建新的合并区域
        CellRangeAddress newRegion = new CellRangeAddress(preRow, currentRow, startCol, endCol);
        sheet.addMergedRegion(newRegion);
        // setBorder(newRegion, sheet);
    }

    /**
     * 设置合并单元格边框
     *
     * 功能说明：
     * 为合并区域设置细边框样式，使合并后的单元格显示边框
     *
     * @param cra 合并区域对象
     * @param sheet Excel工作表
     */
    private void setBorder(CellRangeAddress cra, Sheet sheet) {
        RegionUtil.setBorderBottom(BorderStyle.THIN, cra, sheet);
        RegionUtil.setBorderLeft(BorderStyle.THIN, cra, sheet);
        RegionUtil.setBorderRight(BorderStyle.THIN, cra, sheet);
        RegionUtil.setBorderTop(BorderStyle.THIN, cra, sheet);
    }
}
