package com.ruoyi.web.common.service.impl;

import com.ruoyi.web.common.model.ExportConfig;
import com.ruoyi.web.common.model.ExportField;
import com.ruoyi.web.common.model.MultiLevelHeader;
import com.ruoyi.web.common.service.IExcelExportService;
import com.ruoyi.common.utils.NestedFieldAccessor;
import com.ruoyi.common.utils.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class ExcelExportServiceImpl implements IExcelExportService {

    @Autowired
    private MultiLevelHeaderServiceImpl multiLevelHeaderService;

    @Autowired
    private NestedFieldAccessor nestedFieldAccessor;

    // 默认列宽配置（单位：字符）
    private static final int DEFAULT_COLUMN_WIDTH = 12;
    private static final Map<String, Integer> COLUMN_WIDTH_CONFIG = new HashMap<>();

    static {
        // 配置特定字段的默认宽度
        COLUMN_WIDTH_CONFIG.put("createTime", 15);
        COLUMN_WIDTH_CONFIG.put("amount", 10);
        COLUMN_WIDTH_CONFIG.put("checkAmount", 10);
        COLUMN_WIDTH_CONFIG.put("qualifiedAmount", 10);
        COLUMN_WIDTH_CONFIG.put("tuzaiAmount", 10);
        COLUMN_WIDTH_CONFIG.put("snapKillAmount", 10);
        COLUMN_WIDTH_CONFIG.put("allTuzaiAmount", 10);
        COLUMN_WIDTH_CONFIG.put("dongAmountStr", 10);
        COLUMN_WIDTH_CONFIG.put("weightStr", 12);
        COLUMN_WIDTH_CONFIG.put("roadDealAmount", 10);
        COLUMN_WIDTH_CONFIG.put("illnessDeadAmount", 10);
        COLUMN_WIDTH_CONFIG.put("illnessDiseaseAmount", 10);
        COLUMN_WIDTH_CONFIG.put("qualifiedAmountAfter", 15);
        COLUMN_WIDTH_CONFIG.put("cargoOwner", 15);
        COLUMN_WIDTH_CONFIG.put("drugResult.checkAmount", 10);
        COLUMN_WIDTH_CONFIG.put("drugResult.result", 10);
        COLUMN_WIDTH_CONFIG.put("drugResult.examineItemsStr", 20);
        COLUMN_WIDTH_CONFIG.put("antibioticResult.checkAmount", 10);
        COLUMN_WIDTH_CONFIG.put("antibioticResult.result", 10);
        COLUMN_WIDTH_CONFIG.put("antibioticResult.examineItemsStr", 20);
        COLUMN_WIDTH_CONFIG.put("weight", 10);
        COLUMN_WIDTH_CONFIG.put("dealAmount", 10);
        COLUMN_WIDTH_CONFIG.put("qualifiedAmountBefore", 10);
        COLUMN_WIDTH_CONFIG.put("animalCert", 15);
        COLUMN_WIDTH_CONFIG.put("meatCert", 15);
        COLUMN_WIDTH_CONFIG.put("animalCertNo", 15);
        COLUMN_WIDTH_CONFIG.put("originPlace", 10);
        COLUMN_WIDTH_CONFIG.put("produceName", 10);
    }

    /**
     * 导出Excel（支持多级表头）
     */
    public <T> void exportExcel(List<T> dataList, ExportConfig exportConfig,
                                HttpServletResponse response) {
        try {
            // 过滤选中的字段
            List<ExportField> selectedFields = exportConfig.getFields().stream()
                    .filter(ExportField::getSelected)
                    .collect(Collectors.toList());

            if (selectedFields.isEmpty()) {
                throw new RuntimeException("请至少选择一个导出字段");
            }

            Workbook workbook = createWorkbookWithRowMerge(dataList, selectedFields);

            setResponseHeader(response, exportConfig.getFileName());

            workbook.write(response.getOutputStream());
            workbook.close();

        } catch (Exception e) {
            throw new RuntimeException("导出Excel失败: " + e.getMessage(), e);
        }
    }
    /**
     * 创建支持行合并的Workbook
     */
    private <T> Workbook createWorkbookWithRowMerge(List<T> dataList,
                                                    List<ExportField> selectedFields) {
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("日报表");

        // 构建表头
        List<MultiLevelHeader> multiLevelHeaders = multiLevelHeaderService
                .buildMultiLevelHeaders(selectedFields);
        List<ExportField> leafFields = multiLevelHeaderService
                .getLeafFields(selectedFields);

        int totalHeaderRows = multiLevelHeaderService.calculateTotalRows(multiLevelHeaders);
        createOptimizedHeaderRows(sheet, multiLevelHeaders, totalHeaderRows);

        // 填充数据
        if (dataList != null && !dataList.isEmpty()) {
            fillDataWithRobustListSupport(sheet, dataList, leafFields, totalHeaderRows);
            autoSizeColumnsWithLimit(sheet, leafFields.size());
        }

        return workbook;
    }


    /**
     * 健壮的数据填充方法
     */
    private <T> void fillDataWithRobustListSupport(Sheet sheet, List<T> dataList,
                                                   List<ExportField> leafFields, int startRow) {
        int currentRow = startRow;

        for (T data : dataList) {
            // 计算这个数据对象需要多少行
            int rowsNeeded = calculateRowsNeededWithDebug(data, leafFields);

            System.out.println("=== 处理数据对象 ===");
            System.out.println("需要行数: " + rowsNeeded);

            if (rowsNeeded == 1) {
                // 单行数据
                Row row = sheet.createRow(currentRow);
                fillSingleRowWithDebug(row, data, leafFields, sheet.getWorkbook());
                currentRow++;
            } else {
                // 多行数据（列表字段）
                for (int i = 0; i < rowsNeeded; i++) {
                    Row row = sheet.createRow(currentRow + i);
                    fillMultiRowWithDebug(row, data, leafFields, i, rowsNeeded, sheet.getWorkbook());
                }

                // 合并非列表字段
                mergeCommonFields(sheet, leafFields, currentRow, rowsNeeded);
                currentRow += rowsNeeded;
            }
        }
    }

    /**
     * 带调试信息的行数计算
     */
    private <T> int calculateRowsNeededWithDebug(T data, List<ExportField> leafFields) {
        int maxRows = 1;

        // 找出所有列表字段并计算最大长度
        for (ExportField field : leafFields) {
            if (isListField(field.getFieldName())) {
                String listFieldName = extractListFieldName(field.getFieldName());
                Object listObj = nestedFieldAccessor.getNestedFieldValue(data, listFieldName);

                System.out.println("列表字段: " + listFieldName);
                System.out.println("列表对象: " + listObj);

                if (listObj instanceof List) {
                    int listSize = ((List<?>) listObj).size();
                    System.out.println("列表大小: " + listSize);
                    maxRows = Math.max(maxRows, listSize);
                } else {
                    System.out.println("不是列表类型");
                }
            }
        }

        System.out.println("最终行数: " + maxRows);
        return maxRows;
    }

    /**
     * 带调试信息的单行填充
     */
    private <T> void fillSingleRowWithDebug(Row row, T data, List<ExportField> leafFields, Workbook workbook) {
        row.setHeightInPoints(20);
        for (int i = 0; i < leafFields.size(); i++) {
            ExportField field = leafFields.get(i);
            Object value = getFieldValueWithDebug(data, field, 0, 1);
            Cell cell = row.createCell(i);
            setCellValue(cell, value, field, workbook);
        }
    }

    /**
     * 带调试信息的多行填充
     */
    private <T> void fillMultiRowWithDebug(Row row, T data, List<ExportField> leafFields,
                                           int rowIndex, int totalRows, Workbook workbook) {
        row.setHeightInPoints(20);

        System.out.println("填充第 " + rowIndex + " 行");

        for (int i = 0; i < leafFields.size(); i++) {
            ExportField field = leafFields.get(i);
            Object value = getFieldValueWithDebug(data, field, rowIndex, totalRows);
            Cell cell = row.createCell(i);
            setCellValue(cell, value, field, workbook);
        }
    }

    /**
     * 带调试信息的字段值获取
     */
    private <T> Object getFieldValueWithDebug(T data, ExportField field,
                                              int rowIndex, int totalRows) {
        String fieldPath = field.getFieldName();

        System.out.println("处理字段: " + fieldPath);

        if (isListField(fieldPath)) {
            // 列表字段：获取指定索引的值
            Object value = getListFieldValueWithDebug(data, fieldPath, rowIndex);
            System.out.println("列表字段值: " + value);
            return value;
        } else {
            // 非列表字段：只在第一行显示
            Object value = (rowIndex == 0) ? getSimpleFieldValue(data, fieldPath) : "";
            System.out.println("非列表字段值: " + value);
            return value;
        }
    }

    /**
     * 带调试信息的列表字段值获取
     */
    private <T> Object getListFieldValueWithDebug(T data, String fieldPath, int index) {
        try {
            // 解析字段路径
            String listFieldName = extractListFieldName(fieldPath);
            String propertyName = extractPropertyName(fieldPath);

            System.out.println("解析列表字段:");
            System.out.println("  - 完整路径: " + fieldPath);
            System.out.println("  - 列表字段: " + listFieldName);
            System.out.println("  - 属性名: " + propertyName);
            System.out.println("  - 索引: " + index);

            // 获取列表
            Object listObj = nestedFieldAccessor.getNestedFieldValue(data, listFieldName);
            System.out.println("  - 列表对象: " + listObj);

            if (listObj instanceof List) {
                List<?> list = (List<?>) listObj;
                System.out.println("  - 列表大小: " + list.size());

                if (index < list.size()) {
                    Object listElement = list.get(index);
                    System.out.println("  - 列表元素: " + listElement);

                    if (listElement != null) {
                        if (!propertyName.isEmpty()) {
                            // 从列表元素中获取具体属性值
                            Object propertyValue = nestedFieldAccessor.getNestedFieldValue(listElement, propertyName);
                            System.out.println("  - 属性值: " + propertyValue);
                            return propertyValue != null ? propertyValue : "";
                        } else {
                            // 如果没有属性名，直接返回列表元素（转换为字符串）
                            System.out.println("  - 直接返回列表元素: " + listElement);
                            return listElement.toString();
                        }
                    }
                } else {
                    System.out.println("  - 索引超出范围");
                }
            } else {
                System.out.println("  - 不是列表类型");
            }
        } catch (Exception e) {
            System.err.println("获取列表字段值失败: " + fieldPath + " index: " + index);
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 提取属性名 - 修复版本
     */
    private String extractPropertyName(String fieldPath) {
        if (!fieldPath.contains("[")) {
            return ""; // 不是列表字段
        }

        int bracketEnd = fieldPath.indexOf(']');
        if (bracketEnd == -1) {
            return ""; // 没有闭合括号
        }

        // 检查是否有属性名部分
        if (bracketEnd + 1 < fieldPath.length()) {
            char nextChar = fieldPath.charAt(bracketEnd + 1);
            if (nextChar == '.') {
                // 有属性名部分
                return fieldPath.substring(bracketEnd + 2);
            }
        }

        return ""; // 没有属性名，直接访问列表元素
    }

    /**
     * 获取简单字段值
     */
    private <T> Object getSimpleFieldValue(T data, String fieldPath) {
        Object value = nestedFieldAccessor.getNestedFieldValue(data, fieldPath);
        return value != null ? value : "";
    }




    /**
     * 合并非列表字段
     */
    private void mergeCommonFields(Sheet sheet, List<ExportField> leafFields,
                                   int startRow, int totalRows) {
        if (totalRows <= 1) return;

        for (int i = 0; i < leafFields.size(); i++) {
            ExportField field = leafFields.get(i);
            if (!isListField(field.getFieldName())) {
                CellRangeAddress mergeRegion = new CellRangeAddress(
                        startRow, startRow + totalRows - 1, i, i
                );
                sheet.addMergedRegion(mergeRegion);
            }
        }
    }

    /**
     * 判断是否为列表字段
     */
    private boolean isListField(String fieldPath) {
        return fieldPath.matches(".*\\[\\d+\\].*");
    }

    /**
     * 字段路径解析 - 处理单条数据的情况
     */
    private String extractListFieldName(String fieldPath) {
        if (fieldPath.contains("[")) {
            return fieldPath.substring(0, fieldPath.indexOf('['));
        }
        return fieldPath;
    }

    private String formatDate(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(date);
    }


    /**
     * 创建优化的表头行
     */
    private void createOptimizedHeaderRows(Sheet sheet, List<MultiLevelHeader> headers, int totalRows) {
        // 创建表头样式
        CellStyle headerStyle = createHeaderCellStyle(sheet.getWorkbook());

        // 创建所有表头行并设置行高
        for (int i = 0; i < totalRows; i++) {
            Row row = sheet.createRow(i);
            // 设置表头行高稍高一些，适应多行文本
            row.setHeightInPoints(25);
        }

        // 递归创建表头
        for (MultiLevelHeader header : headers) {
            createOptimizedHeaderCell(sheet, header, headerStyle, totalRows);
        }
    }

    /**
     * 创建优化的表头单元格
     */
    private void createOptimizedHeaderCell(Sheet sheet, MultiLevelHeader header,
                                           CellStyle style, int totalRows) {
        int rowIndex = header.getLevel();
        Row row = sheet.getRow(rowIndex);

        Cell cell = row.createCell(header.getStartCol());
        cell.setCellValue(header.getHeaderName());
        cell.setCellStyle(style);

        // 合并水平单元格
        if (header.getStartCol() < header.getEndCol()) {
            CellRangeAddress cellRange = new CellRangeAddress(
                    rowIndex, rowIndex, header.getStartCol(), header.getEndCol()
            );
            sheet.addMergedRegion(cellRange);
        }

        // 对于叶子节点，如果需要跨多行，合并垂直单元格
        if (header.getChildren().isEmpty() && rowIndex < totalRows - 1) {
            CellRangeAddress verticalRange = new CellRangeAddress(
                    rowIndex, totalRows - 1, header.getStartCol(), header.getEndCol()
            );
            sheet.addMergedRegion(verticalRange);
        }

        // 递归处理子节点
        for (MultiLevelHeader child : header.getChildren()) {
            createOptimizedHeaderCell(sheet, child, style, totalRows);
        }
    }

    /**
     * 带限制的自动调整列宽
     */
    private void autoSizeColumnsWithLimit(Sheet sheet, int columnCount) {
        for (int i = 0; i < columnCount; i++) {
            sheet.autoSizeColumn(i);

            // 获取自动调整后的宽度
            int currentWidth = sheet.getColumnWidth(i);
            int maxWidth = 50 * 256; // 最大50个字符
            int minWidth = 8 * 256;  // 最小8个字符

            // 限制宽度在合理范围内
            if (currentWidth > maxWidth) {
                sheet.setColumnWidth(i, maxWidth);
            } else if (currentWidth < minWidth) {
                sheet.setColumnWidth(i, minWidth);
            }
        }
    }

    /**
     * 创建表头单元格样式
     */
    private CellStyle createHeaderCellStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();

        // 设置字体
        Font font = workbook.createFont();
        font.setBold(true);
        font.setFontHeightInPoints((short) 12);
        font.setFontName("微软雅黑");
        style.setFont(font);

        // 设置对齐方式
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);

        // 设置背景色
        style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);

        // 设置边框
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());

        // 设置自动换行
        style.setWrapText(true);

        return style;
    }

    /**
     * 创建数据单元格样式
     */
    private CellStyle createDataCellStyle(Workbook workbook, ExportField field) {
        CellStyle style = workbook.createCellStyle();

        // 设置字体
        Font font = workbook.createFont();
        font.setFontHeightInPoints((short) 11);
        font.setFontName("宋体");
        style.setFont(font);

        // 设置边框
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        style.setTopBorderColor(IndexedColors.GREY_25_PERCENT.getIndex());
        style.setBottomBorderColor(IndexedColors.GREY_25_PERCENT.getIndex());
        style.setLeftBorderColor(IndexedColors.GREY_25_PERCENT.getIndex());
        style.setRightBorderColor(IndexedColors.GREY_25_PERCENT.getIndex());

        // 根据数据类型设置对齐方式
        if (isNumericField(field)) {
            style.setAlignment(HorizontalAlignment.RIGHT);
        } else if (isDateField(field)) {
            style.setAlignment(HorizontalAlignment.CENTER);
        } else {
            style.setAlignment(HorizontalAlignment.LEFT);
        }
        style.setVerticalAlignment(VerticalAlignment.CENTER);

        // 设置自动换行
        style.setWrapText(true);

        return style;
    }

    /**
     * 创建日期单元格样式
     */
    public CellStyle createDateCellStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();

        // 设置字体
        Font font = workbook.createFont();
        font.setFontHeightInPoints((short) 11);
        font.setFontName("宋体");
        style.setFont(font);

        // 设置边框
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);

        // 设置日期格式
        CreationHelper createHelper = workbook.getCreationHelper();
        style.setDataFormat(createHelper.createDataFormat().getFormat("yyyy-mm-dd"));

        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);

        return style;
    }

    private boolean isNumericField(ExportField field) {
        String fieldName = field.getFieldName().toLowerCase();
        return fieldName.contains("amount") || fieldName.contains("number") ||
                fieldName.contains("count") || fieldName.contains("quantity") ||
                fieldName.contains("weight") || fieldName.contains("id");
    }

    private boolean isDateField(ExportField field) {
        String fieldName = field.getFieldName().toLowerCase();
        return fieldName.contains("time") || fieldName.contains("date");
    }
    /**
     * 设置单元格值
     */
    private void setCellValue(Cell cell, Object value, ExportField field, Workbook workbook) {
        if (value == null) {
            cell.setCellValue("");
        } else if (value instanceof String) {
            cell.setCellValue((String) value);
        } else if (value instanceof Number) {
            cell.setCellValue(((Number) value).doubleValue());
        } else if (value instanceof Date) {
            cell.setCellValue((Date) value);
            // 设置日期样式
            CellStyle dateStyle = createDateCellStyle(workbook);
            cell.setCellStyle(dateStyle);
            return; // 已经设置了样式，直接返回
        } else if (value instanceof Boolean) {
            cell.setCellValue((Boolean) value ? "是" : "否");
        } else {
            cell.setCellValue(value.toString());
        }

        // 设置普通样式
        CellStyle dataStyle = createDataCellStyle(workbook, field);
        cell.setCellStyle(dataStyle);
    }

    private void setResponseHeader(HttpServletResponse response, String fileName) throws UnsupportedEncodingException {
        String finalFileName = StringUtils.isBlank(fileName) ? "导出数据" : fileName;
        if (!finalFileName.endsWith(".xlsx")) {
            finalFileName += ".xlsx";
        }

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("UTF-8");
        String encodedFileName = URLEncoder.encode(finalFileName, "UTF-8")
                .replaceAll("\\+", "%20");
        response.setHeader("Content-Disposition",
                "attachment; filename*=UTF-8''" + encodedFileName);
    }
}