package com.njcn.gather.plan.service.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * 分批读取文件行的工具类
 * 用于处理大文件，避免一次性加载整个文件到内存中导致内存溢出
 */
public class BatchFileReader {
    
    private static final Logger log = LoggerFactory.getLogger(BatchFileReader.class);
    
    /**
     * 默认批次大小
     */
    private static final int DEFAULT_BATCH_SIZE = 10000;
    
    /**
     * 分批读取文件行
     *
     * @param file     要读取的文件
     * @param batchSize 批次大小
     * @param consumer  处理每批数据的消费者函数
     */
    public static void readLinesInBatches(File file, int batchSize, Consumer<List<String>> consumer) {
        readLinesInBatches(file, batchSize, Charset.defaultCharset(), consumer);
    }
    
    /**
     * 分批读取文件行
     *
     * @param file      要读取的文件
     * @param batchSize  批次大小
     * @param charset   文件编码
     * @param consumer   处理每批数据的消费者函数
     */
    public static void readLinesInBatches(File file, int batchSize, Charset charset, Consumer<List<String>> consumer) {
        if (batchSize <= 0) {
            batchSize = DEFAULT_BATCH_SIZE;
        }
        
        if (!FileUtil.exist(file)) {
            log.warn("文件不存在: {}", file.getAbsolutePath());
            return;
        }
        
        try (BufferedReader reader = IoUtil.getReader(new InputStreamReader(FileUtil.getInputStream(file), charset))) {
            List<String> batchLines = new ArrayList<>(batchSize);
            String line;
            int count = 0;
            
            while ((line = reader.readLine()) != null) {
                batchLines.add(line);
                count++;
                
                // 当达到批次大小时，处理这一批数据
                if (count % batchSize == 0) {
                    if (CollUtil.isNotEmpty(batchLines)) {
                        consumer.accept(batchLines);
                        batchLines = new ArrayList<>(batchSize);
                    }
                }
            }
            
            // 处理最后一批数据（不足一批的数据）
            if (CollUtil.isNotEmpty(batchLines)) {
                consumer.accept(batchLines);
            }
            
        } catch (IOException e) {
            log.error("读取文件失败: {}", file.getAbsolutePath(), e);
            throw new RuntimeException("读取文件失败: " + file.getAbsolutePath(), e);
        }
    }
    
    /**
     * 分批读取文件行（使用默认批次大小）
     *
     * @param file     要读取的文件
     * @param consumer 处理每批数据的消费者函数
     */
    public static void readLinesInBatches(File file, Consumer<List<String>> consumer) {
        readLinesInBatches(file, DEFAULT_BATCH_SIZE, consumer);
    }
    
    /**
     * 分批读取文件行（使用默认编码）
     *
     * @param filePath  文件路径
     * @param batchSize 批次大小
     * @param consumer  处理每批数据的消费者函数
     */
    public static void readLinesInBatches(String filePath, int batchSize, Consumer<List<String>> consumer) {
        readLinesInBatches(FileUtil.file(filePath), batchSize, consumer);
    }
    
    /**
     * 分批读取文件行（使用默认编码和批次大小）
     *
     * @param filePath 文件路径
     * @param consumer 处理每批数据的消费者函数
     */
    public static void readLinesInBatches(String filePath, Consumer<List<String>> consumer) {
        readLinesInBatches(FileUtil.file(filePath), DEFAULT_BATCH_SIZE, consumer);
    }
}