package com.yd.oss.service.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import com.alibaba.fastjson.JSON;
import com.yd.oss.feign.result.ImportResult;
import com.yd.oss.feign.result.ValidationResult;
import com.yd.oss.service.service.ExcelImportService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.util.*;

/**
 * 通用Excel导入工具类
 * 支持动态表头解析
 */
@Slf4j
@Service
public class ExcelImportServiceImpl implements ExcelImportService {

    /**
     * 通用Excel导入
     * @param file Excel文件
     * @param headerRow 表头行号（默认第1行，从0开始）
     * @param dataStartRow 数据开始行号（默认第2行，从0开始）
     * @param requiredFields 必填字段列表
     * @return 导入结果
     */
    @Override
    public ImportResult genericImport(MultipartFile file,
                                      Integer headerRow,
                                      Integer dataStartRow,
                                      List<String> requiredFields) {

        ImportResult result = new ImportResult();

        try {
            // 参数默认值处理
            int headerRowNum = headerRow != null ? headerRow : 0;
            int dataStartRowNum = dataStartRow != null ? dataStartRow : 1;

            // 1. 获取表头信息
            List<String> headers = getExcelHeaders(file, headerRowNum);
            result.setHeaders(headers);

            // 2. 导入Excel数据
            ExcelImportResult<Map<String, Object>> importResult =
                    importExcel(file, headerRowNum, dataStartRowNum);

            System.out.println(JSON.toJSONString(importResult.getList()));
            // 3. 处理导入结果
            List<Map<String, Object>> data =
                    processImportResult(importResult, headers);
            result.setData(data);
            result.setTotalCount(data.size());

            // 4. 数据验证
            if (requiredFields != null && !requiredFields.isEmpty()) {
                ValidationResult validationResult =
                        validateData(data, requiredFields);
                result.setValid(validationResult.isValid());
                result.setErrorMessages(validationResult.getErrors());
            } else {
                result.setValid(true);
            }

            result.setSuccess(true);
            result.setMessage("导入成功，共导入" + data.size() + "条数据");

        } catch (Exception e) {
            result.setSuccess(false);
            result.setMessage("导入失败：" + e.getMessage());
        }

        return result;
    }

    /**
     * 简化的导入方法（使用默认参数）
     * @param file
     * @return
     */
    @Override
    public ImportResult simpleImport(MultipartFile file) {
        return genericImport(file, 0, 1, null);
    }

    /**
     * 通用Excel导入方法
     * @param file Excel文件
     * @param headerRowNum 表头所在行号（从0开始）
     * @param dataStartRowNum 数据开始行号（从0开始）
     * @return 导入结果
     */
    public static ExcelImportResult<Map<String, Object>> importExcel(
            MultipartFile file,
            int headerRowNum,
            int dataStartRowNum) throws Exception {

        ImportParams params = new ImportParams();
        params.setHeadRows(headerRowNum + 1); // 表头行数（从1开始计数）

        // EasyPOI的startRows是从0开始计数，但表示的是跳过多少行
        // 如果要从第2行开始（索引1），需要设置为1，但这样会跳过第2行
        // 正确的做法：如果要读取从dataStartRowNum开始的行，应该设置为dataStartRowNum
        params.setStartRows(dataStartRowNum);

        params.setNeedVerify(true);

        // 使用Map接收数据
        return ExcelImportUtil.importExcelMore(
                file.getInputStream(),
                Map.class,
                params
        );
    }
    
    /**
     * 获取Excel表头信息
     * @param file Excel文件
     * @param headerRowNum 表头所在行号（从0开始）
     * @return 表头字段列表
     */
    public static List<String> getExcelHeaders(MultipartFile file, int headerRowNum) throws Exception {
        List<String> headers = new ArrayList<>();

        // 修正：使用WorkbookFactory.create()静态方法
        try (Workbook workbook = WorkbookFactory.create(file.getInputStream())) {
            Sheet sheet = workbook.getSheetAt(0);
            Row headerRow = sheet.getRow(headerRowNum);

            if (headerRow != null) {
                for (Cell cell : headerRow) {
                    String headerValue = getCellValue(cell);
                    if (headerValue != null && !headerValue.trim().isEmpty()) {
                        headers.add(headerValue.trim());
                    }
                }
            }
        }
        return headers;
    }

    /**
     * 获取单元格值
     * @param cell
     * @return
     */
    public static String getCellValue(Cell cell) {
        if (cell == null) {
            return null;
        }
        
        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                return String.valueOf(cell.getNumericCellValue());
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                return cell.getCellFormula();
            default:
                return "";
        }
    }

    /**
     * 处理导入结果，转换为更友好的数据结构，并过滤空行
     * @param result 导入结果
     * @param headers 表头信息
     * @return 处理后的数据
     */
    public static List<Map<String, Object>> processImportResult(
            ExcelImportResult<Map<String, Object>> result,
            List<String> headers) {

        List<Map<String, Object>> processedData = new ArrayList<>();

        if (result != null && result.getList() != null) {
            for (Map<String, Object> rowData : result.getList()) {
                // 检查是否为空行
                if (isEmptyRow(rowData, headers)) {
                    continue; // 跳过空行
                }

                Map<String, Object> processedRow = new LinkedHashMap<>();

                // 按照表头顺序重新组织数据
                for (String header : headers) {
                    processedRow.put(header, rowData.get(header));
                }

                processedData.add(processedRow);
            }
        }

        return processedData;
    }

    /**
     * 判断一行数据是否为空行
     * @param rowData 行数据
     * @param headers 表头列表
     * @return true-空行, false-非空行
     */
    private static boolean isEmptyRow(Map<String, Object> rowData, List<String> headers) {
        if (rowData == null || rowData.isEmpty()) {
            return true;
        }

        // 检查所有业务字段是否都为空（排除excelRowNum等系统字段）
        for (String header : headers) {
            Object value = rowData.get(header);
            if (value != null && !value.toString().trim().isEmpty()) {
                return false; // 发现非空值，不是空行
            }
        }

        // 额外检查：如果只有系统字段有值，也算空行
        boolean hasOnlySystemFields = true;
        for (String key : rowData.keySet()) {
            if (!key.equals("excelRowNum") && !key.startsWith("_")) {
                Object value = rowData.get(key);
                if (value != null && !value.toString().trim().isEmpty()) {
                    hasOnlySystemFields = false;
                    break;
                }
            }
        }

        return hasOnlySystemFields;
    }
    
    /**
     * 验证导入数据
     * @param data 导入的数据
     * @param requiredFields 必填字段
     * @return 验证结果
     */
    public static ValidationResult validateData(List<Map<String, Object>> data, List<String> requiredFields) {
        ValidationResult result = new ValidationResult();
        result.setValid(true);
        
        for (int i = 0; i < data.size(); i++) {
            Map<String, Object> row = data.get(i);
            int rowNum = i + 1; // 实际行号（从1开始）
            
            // 检查必填字段
            for (String field : requiredFields) {
                Object value = row.get(field);
                if (value == null || value.toString().trim().isEmpty()) {
                    result.setValid(false);
                    result.getErrors().add("第" + rowNum + "行，字段[" + field + "]不能为空");
                }
            }
            
            // 这里可以添加更多的验证规则
            // 例如：数据类型验证、格式验证等
        }
        return result;
    }

}