package com.qianhe.util;

import com.qianhe.common.exception.BusinessException;
import com.qianhe.common.utils.StringUtils;
import com.qianhe.domain.ExcelCellConfig;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Consumer;

/**
 * 自定义Excel导入工具类
 */
public class MtExcelImportUtils {
    private static final DataFormatter DATA_FORMATTER = new DataFormatter();

    /**
     * 通用Excel导入方法（XLSX格式）
     * @param file          上传的Excel文件
     * @param skipHeader    是否跳过标题行（true=跳过第0行，false=不跳过）
     * @param rowParser     行数据解析器：参数（行号、行对象）→ 返回解析后的业务对象
     * @param batchHandler  批量数据处理器：接收解析后的业务数据列表，执行批量插入/更新等操作
     * @param <T>           业务对象类型（如ZqczPwxx、ZqczRyxx）
     * @return              处理的记录数
     * @throws BusinessException 业务异常
     */
    public static <T> int importXlsx(MultipartFile file,
                                     boolean skipHeader,
                                     BiFunction<Integer, XSSFRow, T> rowParser,
                                     Consumer<List<T>> batchHandler) {
        // 1. 前置校验
        if (file == null || file.isEmpty()) {
            throw new BusinessException("上传的Excel文件不能为空");
        }
        if (!file.getOriginalFilename().endsWith(".xlsx")) {
            throw new BusinessException("仅支持.xlsx格式的Excel文件");
        }

        XSSFWorkbook workbook = null;
        try {
            workbook = new XSSFWorkbook(file.getInputStream());
            XSSFSheet sheet = workbook.getSheetAt(0); // 读取第一个sheet
            int lastRowNum = sheet.getLastRowNum();
            List<T> dataList = new ArrayList<>();

            // 2. 遍历行数据
            for (int i = 0; i <= lastRowNum; i++) {
                // 跳过标题行
                if (skipHeader && i == 0) {
                    continue;
                }

                XSSFRow row = sheet.getRow(i);
                if (row == null) {
                    continue; // 跳过空行
                }

                // 3. 调用业务侧的行解析逻辑
                T businessObj = rowParser.apply(i, row);
                if (businessObj != null) {
                    dataList.add(businessObj);
                }
            }

            // 4. 校验解析结果
            if (Optional.ofNullable(dataList).orElse(Collections.emptyList()).isEmpty()) {
                throw new BusinessException("读取Excel文件失败，上传数据为空");
            }

            // 5. 调用业务侧的批量处理逻辑
            batchHandler.accept(dataList);

            return dataList.size();
        } catch (BusinessException e) {
            throw e; // 业务异常直接抛出
        } catch (IOException e) {
            throw new BusinessException("读取Excel文件失败，请检查文件格式或是否损坏");
        } finally {
            // 6. 关闭资源（避免内存泄漏）
            if (workbook != null) {
                try {
                    workbook.close();
                } catch (IOException ignored) {
                }
            }
        }
    }

    /**
     * 批量解析Excel行数据并做非空校验
     * @param row          当前行对象
     * @param rowNum       当前行号（用于错误提示）
     * @param cellConfigs  单元格解析配置列表
     * @return             解析结果：key=字段名，value=单元格值
     * @throws BusinessException 校验失败抛出异常
     */
    public static Map<String, String> parseAndValidateCells(XSSFRow row, int rowNum, List<ExcelCellConfig> cellConfigs) {
        Map<String, String> cellValueMap = new HashMap<>();

        for (ExcelCellConfig config : cellConfigs) {
            // 1. 解析单元格值（处理null单元格）
            String cellValue = "";
            if (row.getCell(config.getCellIndex()) != null) {
                cellValue = DATA_FORMATTER.formatCellValue(row.getCell(config.getCellIndex())).trim();
            }

            // 2. 非空校验
            if (config.isRequired() && StringUtils.isEmpty(cellValue)) {
                throw new BusinessException(
                        String.format("导入失败，第%d行%s不能为空", rowNum + 1, config.getFieldName())
                );
            }

            // 3. 存入解析结果
            cellValueMap.put(config.getFieldName(), cellValue);
        }

        return cellValueMap;
    }

    /**
     * 安全转换为整数（用于Excel数字字段解析）
     * @param cellValue 单元格原始值
     * @param fieldName 字段名称（用于错误提示）
     * @param rowNum    行号（用于错误提示）
     * @return 转换后的整数
     * @throws BusinessException 转换失败抛出友好异常
     */
    public static Integer safeParseInt(String cellValue, String fieldName, int rowNum) {
        // 1. 空值校验（已在parseAndValidateCells中做过，这里兜底）
        if (StringUtils.isEmpty(cellValue)) {
            throw new BusinessException(String.format("导入失败，第%d行%s不能为空", rowNum + 1, fieldName));
        }

        try {
            // 2. 尝试转换为整数（兼容带小数点的数字，如"10.0"转为10）
            double doubleValue = Double.parseDouble(cellValue.trim());
            if (doubleValue % 1 != 0) {
                throw new BusinessException(String.format("导入失败，第%d行%s必须为整数（当前值：%s）", rowNum + 1, fieldName, cellValue));
            }
            return (int) doubleValue;
        } catch (NumberFormatException e) {
            // 3. 转换失败抛出友好异常
            throw new BusinessException(String.format("导入失败，第%d行%s必须为数字（当前值：%s）", rowNum + 1, fieldName, cellValue));
        }
    }
}
