package com.yami.shop.utils;

import com.yami.shop.bean.model.ExportTask;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.scheduling.annotation.Async;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.rmi.server.ExportException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.regex.Pattern;

/**
 * 导出工具类
 * @author zx
 * @date 2015-12-12 00:00:00
 */
@Log4j2
public class ExportUtils {
    private static final Pattern UNSAFE_PATTERN =
            Pattern.compile("(\\.\\.|[/\\\\][.]+[/\\\\]|//|\\\\\\\\)");

    private static final Set<String> BLACKLISTED_PATHS = Set.of(
            "/etc/", "/bin/", "/sbin/", "/usr/", "/var/", "/proc/",
            "C:\\Windows\\", "C:\\Program Files\\", "C:\\ProgramData\\"
    );

    /**
     * 导出文件保存路径
     */
    public static String savePath = "/opt/dev_projects";
//    /**
//     * 本地导出文件保存路径
//     */
//    public static String savePath = "D:\\test\\exports\\";

    /**
     * 单个文件大小限制(MB)
     */
    private static int maxFileSize = 100;
    /**
     * 允许的导出文件类型
     */
    private static  List<String> allowedExtensions = Arrays.asList(".xlsx", ".xls", ".csv");
    /**
     * 创建合并单元格的表头（模拟模板中的"正常订单"标题）
     */
    public static void createMergedHeader(Sheet sheet, CellStyle headerStyle,String headerName,int lastCol) {
        // 第一行：主标题
        Row titleRow = sheet.createRow(0);
        Cell titleCell = titleRow.createCell(0);
        titleCell.setCellValue(headerName);
        titleCell.setCellStyle(headerStyle);

        // 合并单元格
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, lastCol));

        // 设置行高
        titleRow.setHeightInPoints(25);
    }

    /**
     * 设置HTTP响应头
     */
    public static void setupResponse(HttpServletResponse response, String fileName) {
        try {
            String encodedFileName = URLEncoder.encode(fileName, "UTF-8")
                    .replaceAll("\\+", "%20");

            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Content-Disposition",
                    "attachment; filename*=UTF-8''" + encodedFileName + ".xlsx");
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");

        } catch (Exception e) {
            throw new RuntimeException("设置响应头失败", e);
        }
    }
    /**
     * 创建列标题行
     */
    public static  void createColumnHeaders(Sheet sheet, CellStyle headerStyle,String[] headers) {
        Row headerRow = sheet.createRow(1);
        headerRow.setHeightInPoints(20);
        for (int i = 0; i < headers.length; i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers[i]);
            cell.setCellStyle(headerStyle);
        }
    }

    /**
     * 创建单元格（字符串类型）
     */
    public static void createCell(Sheet sheet,Row row,int col, int size,int rowNum, String value, CellStyle style) {
        int lastRow = rowNum + size - 1;
        if (lastRow > rowNum) {
            if (!isMergeRegionOverlap(sheet, rowNum-1, lastRow-1, col)){ //因为索引是从0开始的  所以开始行和结束行都需要减1
                CellRangeAddress cellAddresses = new CellRangeAddress(rowNum - 1, lastRow - 1, col, col);
                sheet.addMergedRegion(cellAddresses);
                setMergedRegionBorder(sheet,cellAddresses);
            }
        }
        Cell cell = row.createCell(col);
        cell.setCellValue(value != null ? value : "");
        cell.setCellStyle(style);

    }

    /**
     * 创建单元格（数字类型）
     */
    public static void createCell(Sheet sheet, Row row, int col, int size, int rowNum, BigDecimal value, CellStyle style) {
        int lastRow = rowNum + size - 1;
        if (lastRow > rowNum) {
            if (!isMergeRegionOverlap(sheet, rowNum-1, lastRow-1, col)){
                CellRangeAddress cellAddresses = new CellRangeAddress(rowNum - 1, lastRow - 1, col, col);
                sheet.addMergedRegion(cellAddresses);
                setMergedRegionBorder(sheet,cellAddresses);
            }
        }
        Cell cell = row.createCell(col);
        if (value != null) {
            cell.setCellValue(value.doubleValue());
        } else {
            cell.setCellValue(0);
        }
        cell.setCellStyle(style);
    }
    /**
     * 创建单元格（数字类型）
     */
    public static void createCell(Sheet sheet,Row row,int col, int size,int rowNum, double value, CellStyle style) {
        int lastRow = rowNum + size - 1;
        if (lastRow > rowNum) {
            if (!isMergeRegionOverlap(sheet, rowNum-1, lastRow-1, col)){
                CellRangeAddress cellAddresses = new CellRangeAddress(rowNum - 1, lastRow - 1, col, col);
                sheet.addMergedRegion(cellAddresses);
                setMergedRegionBorder(sheet,cellAddresses);
            }
        }
        Cell cell = row.createCell(col);
        cell.setCellValue(value);
        cell.setCellStyle(style);
    }

    /**
     * 创建单元格（整数类型）
     */
    public static void createCell(Sheet sheet,Row row,int col, int size,int rowNum,  Integer value, CellStyle style) {
        int lastRow = rowNum + size - 1;
        if (lastRow > rowNum) {
            if (!isMergeRegionOverlap(sheet, rowNum-1, lastRow-1, col)){
                CellRangeAddress cellAddresses = new CellRangeAddress(rowNum - 1, lastRow - 1, col, col);
                sheet.addMergedRegion(cellAddresses);
                setMergedRegionBorder(sheet,cellAddresses);
            }
        }
        Cell cell = row.createCell(col);
        if (value != null) {
            cell.setCellValue(value);
        } else {
            cell.setCellValue(0);
        }
        cell.setCellStyle(style);
    }

    /**
     * 创建表头样式
     */
    public static CellStyle createHeaderStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();

        // 字体设置
        Font font = workbook.createFont();
        font.setBold(true);
        font.setFontHeightInPoints((short) 11);
        font.setColor(IndexedColors.WHITE.getIndex());
        style.setFont(font);

        // 背景色 - 深蓝色
        style.setFillForegroundColor(IndexedColors.DARK_BLUE.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);

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

        // 边框
        setBorderStyle(style);

        return style;
    }

    /**
     * 创建数据样式
     */
    public static CellStyle createDataStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();

        Font font = workbook.createFont();
        font.setFontHeightInPoints((short) 10);
        style.setFont(font);

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

        return style;
    }

    /**
     * 创建数字样式
     */
    public static CellStyle createNumberStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();

        Font font = workbook.createFont();
        font.setFontHeightInPoints((short) 10);
        style.setFont(font);

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

        // 数字格式：保留2位小数
        DataFormat format = workbook.createDataFormat();
        style.setDataFormat(format.getFormat("0.00"));
        setBorderStyle(style);

        return style;
    }

    /**
     * 创建日期样式
     */
    public static CellStyle createDateStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();

        Font font = workbook.createFont();
        font.setFontHeightInPoints((short) 10);
        style.setFont(font);

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

        // 日期格式
        DataFormat format = workbook.createDataFormat();
        style.setDataFormat(format.getFormat("yyyy-MM-dd HH:mm"));
        setBorderStyle(style);

        return style;
    }

    /**
     * 设置边框样式
     */
    public static void setBorderStyle(CellStyle style) {
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
    }
    /**
     * 为合并区域设置边框样式（重用样式，减少创建次数）
     */
    public static void setMergedRegionBorder(Sheet sheet, CellRangeAddress mergedRegion) {
        int firstRow = mergedRegion.getFirstRow();
        int lastRow = mergedRegion.getLastRow();
        int firstCol = mergedRegion.getFirstColumn();
        int lastCol = mergedRegion.getLastColumn();

        Workbook workbook = sheet.getWorkbook();

        // 为不同的边框组合创建样式
        Map<String, CellStyle> styleMap = new HashMap<>();

        for (int row = firstRow; row <= lastRow; row++) {
            Row sheetRow = sheet.getRow(row);
            if (sheetRow == null) {
                sheetRow = sheet.createRow(row);
            }

            for (int col = firstCol; col <= lastCol; col++) {
                // 生成样式key
                String styleKey = generateStyleKey(row, col, firstRow, lastRow, firstCol, lastCol);

                CellStyle borderStyle = styleMap.get(styleKey);
                if (borderStyle == null) {
                    borderStyle = workbook.createCellStyle();

                    // 设置左边框（只有最左侧单元格）
                    if (col == firstCol) {
                        borderStyle.setBorderLeft(BorderStyle.THIN);
                        borderStyle.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
                    }

                    // 设置右边框（只有最右侧单元格）
                    if (col == lastCol) {
                        borderStyle.setBorderRight(BorderStyle.THIN);
                        borderStyle.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
                    }

                    // 设置上边框（只有最上方单元格）
                    if (row == firstRow) {
                        borderStyle.setBorderTop(BorderStyle.THIN);
                        borderStyle.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
                    }

                    // 设置下边框（只有最下方单元格）
                    if (row == lastRow) {
                        borderStyle.setBorderBottom(BorderStyle.THIN);
                        borderStyle.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
                    }

                    // 如果是左上角单元格，设置居中
                    if (row == firstRow && col == firstCol) {
                        setCenterAlignment(borderStyle);
                    }

                    styleMap.put(styleKey, borderStyle);
                }

                Cell cell = sheetRow.getCell(col);
                if (cell == null) {
                    cell = sheetRow.createCell(col);
                }

                cell.setCellStyle(borderStyle);
            }
        }
    }

    private static String generateStyleKey(int row, int col, int firstRow, int lastRow, int firstCol, int lastCol) {
        StringBuilder key = new StringBuilder();

        // 标识位置类型
        if (row == firstRow) key.append("T");
        if (row == lastRow) key.append("B");
        if (col == firstCol) key.append("L");
        if (col == lastCol) key.append("R");

        // 特殊标记左上角单元格
        if (row == firstRow && col == firstCol) {
            key.append("_CENTER");
        }

        return key.toString();
    }
//    /**
//     * 为合并区域设置边框样式
//     */
//    public static void setMergedRegionBorder(Sheet sheet, CellRangeAddress mergedRegion) {
//        int firstRow = mergedRegion.getFirstRow();
//        int lastRow = mergedRegion.getLastRow();
//        int firstCol = mergedRegion.getFirstColumn();
//        int lastCol = mergedRegion.getLastColumn();
//
//        // 为合并区域的每个单元格设置特定边框
//        for (int row = firstRow; row <= lastRow; row++) {
//            for (int col = firstCol; col <= lastCol; col++) {
//                Row sheetRow = sheet.getRow(row);
//                if (sheetRow == null) {
//                    sheetRow = sheet.createRow(row);
//                }
//                Cell cell = sheetRow.getCell(col);
//                if (cell == null) {
//                    cell = sheetRow.createCell(col);
//                }
//
//                CellStyle borderStyle = sheet.getWorkbook().createCellStyle();
//
//                // 设置左边框（只有最左侧单元格）
//                if (col == firstCol) {
//                    borderStyle.setBorderLeft(BorderStyle.THIN);
//                    borderStyle.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
//                }
//
//                // 设置右边框（只有最右侧单元格）
//                if (col == lastCol) {
//                    borderStyle.setBorderRight(BorderStyle.THIN);
//                    borderStyle.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
//                }
//
//                // 设置上边框（只有最上方单元格）
//                if (row == firstRow) {
//                    borderStyle.setBorderTop(BorderStyle.THIN);
//                    borderStyle.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
//                }
//
//                // 设置下边框（只有最下方单元格）
//                if (row == lastRow) {
//                    borderStyle.setBorderBottom(BorderStyle.THIN);
//                    borderStyle.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
//                }
//                // 如果是左上角单元格，设置居中
//                if (row == firstRow && col == firstCol) {
//                    setCenterAlignment(borderStyle);
//                    // 可选：设置自动换行
////                    borderStyle.setWrapText(true);
//                }
//
//                cell.setCellStyle(borderStyle);
//            }
//        }
//    }
    /**
     * 设置居中对齐
     */
    public static void setCenterAlignment(CellStyle style) {
        // 水平居中
        style.setAlignment(HorizontalAlignment.CENTER);
        // 垂直居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);
    }
    /**
     * 格式化日期
     */
    public static String formatDate(Date date) {
        if (date == null) return "";

        // 使用java.time格式化（Java 8+）
        return java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
                .format(date.toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDateTime());
    }
    /**
     * 检查合并区域是否重叠
     */
    public static boolean isMergeRegionOverlap(Sheet sheet, int startRow, int endRow, int column) {
        for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
            CellRangeAddress existingRegion = sheet.getMergedRegion(i);
            if (existingRegion.getFirstColumn() == column &&
                    existingRegion.getLastColumn() == column) {
                // 检查行重叠
                if (!(endRow < existingRegion.getFirstRow() || startRow > existingRegion.getLastRow())) {
                    return true; // 存在重叠
                }
            }
        }
        return false;
    }


    public static String sanitize(String filePath) {
        if (StringUtils.isEmpty(filePath)) {
            throw new IllegalArgumentException("文件路径不能为空");
        }

        // 移除空字符
        filePath = filePath.replaceAll("\\x00", "");

        // 检测路径遍历攻击
        if (UNSAFE_PATTERN.matcher(filePath).find()) {
            throw new SecurityException("检测到非法路径字符");
        }

        // 规范化路径
        Path normalizedPath = Paths.get(filePath).normalize();

        // 检查黑名单路径
        String normalizedStr = normalizedPath.toString().toLowerCase();
        for (String blacklisted : BLACKLISTED_PATHS) {
            if (normalizedStr.startsWith(blacklisted.toLowerCase())) {
                throw new SecurityException("禁止访问系统目录");
            }
        }

        return normalizedPath.toString();
    }

    /**
     * 生成安全的文件名
     */
    public static String generateSafeFileName(String originalName) {
        // 移除特殊字符，防止路径遍历攻击
        String safeName = originalName.replaceAll("[\\\\/:*?\"<>|]", "");

        // 添加时间戳和随机数防止冲突
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
        String random = String.valueOf(ThreadLocalRandom.current().nextInt(1000, 9999));

        if (safeName.endsWith(".xlsx")) {
            String nameWithoutExt = safeName.substring(0, safeName.length() - 5);
            return String.format("%s_%s_%s.xlsx", nameWithoutExt, timestamp, random);
        } else {
            return String.format("%s_%s_%s.xlsx", safeName, timestamp, random);
        }
    }
    /**
     * 准备导出文件
     */
    public static void prepareExportFile(String fileName, ExportTask exportTask)
            throws ExportException {

        try {
            // 创建按日期和操作人分组的目录结构
            String dateStr = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
            String userDir = DigestUtils.md5DigestAsHex(exportTask.getUserId().toString().getBytes()).substring(0, 8);

            // 完整保存路径
            String fullSavePath = savePath +
                    "orders/" + dateStr + "/" + userDir + "/";

            // 创建目录
            File saveDir = new File(fullSavePath);
            if (!saveDir.exists()) {
                boolean created = saveDir.mkdirs();
                if (!created) {
                    throw new ExportException("创建保存目录失败: " + fullSavePath);
                }

                // 设置目录权限（Linux系统）
                if (!System.getProperty("os.name").toLowerCase().contains("windows")) {
                    Runtime.getRuntime().exec("chmod 755 " + saveDir.getAbsolutePath());
                }
            }
            // 检查磁盘空间
            checkDiskSpace(saveDir);
            File file = new File(fullSavePath, fileName);
            // 记录文件信息
            exportTask.setFileUrl(file.getAbsolutePath());
            exportTask.setFileName(fileName);
            exportTask.setFullPath(fullSavePath);

        } catch (IOException e) {
            throw new ExportException("准备导出文件失败", e);
        }
    }
    /**
     * 检查磁盘空间
     */
    private static void checkDiskSpace(File directory) throws ExportException {
        try {
            long freeSpace = directory.getFreeSpace();
            long minRequiredSpace = maxFileSize * 1024L * 1024L;

            if (freeSpace < minRequiredSpace) {
                throw new ExportException(String.format(
                        "磁盘空间不足，剩余: %.2fMB, 需要: %dMB",
                        freeSpace / 1024.0 / 1024.0,
                        maxFileSize
                ));
            }
        } catch (Exception e) {
            throw new ExportException("检查磁盘空间失败", e);
        }
    }
    public static String getContentType(File file) {
        String fileName = file.getName();
        String extension = "";

        int lastDotIndex = fileName.lastIndexOf('.');
        if (lastDotIndex > 0) {
            extension = fileName.substring(lastDotIndex + 1).toLowerCase();
        }

        // 根据文件扩展名返回对应的 MIME 类型
        switch (extension) {
            case "pdf":
                return "application/pdf";
            case "txt":
                return "text/plain";
            case "html":
            case "htm":
                return "text/html";
            case "css":
                return "text/css";
            case "js":
                return "application/javascript";
            case "json":
                return "application/json";
            case "xml":
                return "application/xml";
            case "jpg":
            case "jpeg":
                return "image/jpeg";
            case "png":
                return "image/png";
            case "gif":
                return "image/gif";
            case "bmp":
                return "image/bmp";
            case "mp4":
                return "video/mp4";
            case "mp3":
                return "audio/mpeg";
            case "zip":
                return "application/zip";
            case "doc":
            case "docx":
                return "application/msword";
            case "xls":
                return "application/vnd.ms-excel";
            case "xlsx":
                return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
            case "ppt":
            case "pptx":
                return "application/vnd.ms-powerpoint";
            case "csv":
                return "text/csv";
            default:
                return "application/octet-stream";  // 默认二进制流
        }
    }

    /**
     * 异步清理临时文件待修改
     */
//    @Async
//    public static void cleanTempFilesAsync(String filePath) {
//        try {
//            File directory = new File(filePath);
//            if (directory.exists() && directory.isDirectory()) {
//                File[] files = directory.listFiles();
//                if (files != null) {
//                    LocalDateTime expireTime = LocalDateTime.now()
//                            .minusDays(retentionDays);
//
//                    for (File file : files) {
//                        if (file.isFile() && file.getName().endsWith(".xlsx")) {
//                            // 删除过期文件
//                            BasicFileAttributes attrs = Files.readAttributes(
//                                    file.toPath(), BasicFileAttributes.class);
//                            LocalDateTime fileTime = LocalDateTime.ofInstant(
//                                    attrs.creationTime().toInstant(), ZoneId.systemDefault());
//
//                            if (fileTime.isBefore(expireTime)) {
//                                boolean deleted = file.delete();
//                                if (deleted) {
//                                    log.info("删除过期导出文件: {}", file.getAbsolutePath());
//                                }
//                            }
//                        }
//                    }
//                }
//            }
//        } catch (Exception e) {
//            log.warn("清理临时文件失败", e);
//        }
//    }


}
