package jnpf.attendance.service.handle.notification;

import jnpf.config.CustomTenantUtil;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

@Component
@Slf4j
public class MultiTenantTimeSizeBatchProcessor<T> {
    // 租户处理器映射
    private final Map<String, TenantBatchHandler<T>> tenantHandlers = new ConcurrentHashMap<>();


    // 共享资源管理
    private final TenantResourceManager tenantResourceManager;
    private final CustomTenantUtil customTenantUtil;
    
    // 定期清理不活跃租户的调度器
    private final ScheduledExecutorService cleanupScheduler = Executors.newScheduledThreadPool(1);
    
    public MultiTenantTimeSizeBatchProcessor(
            TenantResourceManager tenantResourceManager,
            CustomTenantUtil customTenantUtil) {
        this.tenantResourceManager = tenantResourceManager;
        this.customTenantUtil = customTenantUtil;
        
        // 启动定期清理任务
        cleanupScheduler.scheduleAtFixedRate(
            this::cleanupInactiveHandlers, 30, 30, TimeUnit.MINUTES);
    }
    
    /**
     * 添加数据到批处理队列
     * @param tenantId 租户ID
     * @param data 要处理的数据
     */
    public void addData(String tenantId, T data) {
        // 获取或创建租户处理器
        TenantBatchHandler<T> handler = tenantHandlers.computeIfAbsent(
            tenantId, 
            id -> new TenantBatchHandler<>(id, tenantResourceManager, customTenantUtil)
        );
        
        // 添加数据到处理器
        handler.addData(data);
    }
    
    /**
     * 清理不活跃的租户处理器
     */
    private void cleanupInactiveHandlers() {
        long currentTime = System.currentTimeMillis();
        long inactiveThreshold = 30 * 60 * 1000; // 30分钟不活跃
        
        tenantHandlers.entrySet().removeIf(entry -> {
            TenantBatchHandler<T> handler = entry.getValue();
            if (currentTime - handler.getLastActiveTime() > inactiveThreshold) {
                handler.cleanup();
                log.info("Cleaned up inactive tenant handler: {}", entry.getKey());
                return true;
            }
            return false;
        });
    }
    
    @PreDestroy
    public void shutdown() {
        cleanupScheduler.shutdown();
        tenantHandlers.values().forEach(TenantBatchHandler::cleanup);
        log.info("MultiTenantTimeSizeBatchProcessor shutdown completed");
    }
    
    /**
     * 租户专用批处理器 - 实现时间和数量双重触发机制
     */
    private static class TenantBatchHandler<T> {
        // 数据缓冲区
        private final List<T> buffer = new ArrayList<>();
        private final Object lock = new Object();
        
        // 定时器管理
        private final ScheduledExecutorService scheduler;
        private ScheduledFuture<?> currentTimer;
        
        // 租户信息
        private final String tenantId;
        private final TenantResourceManager tenantResourceManager;
        private final CustomTenantUtil customTenantUtil;
        @Getter
        private volatile long lastActiveTime;
        
        // 批处理配置 - 根据租户规模动态调整
        private final int batchSize;
        private final long timeInterval;
        
        public TenantBatchHandler(String tenantId, 
                                TenantResourceManager tenantResourceManager,
                                CustomTenantUtil customTenantUtil) {
            this.tenantId = tenantId;
            this.tenantResourceManager = tenantResourceManager;
            this.customTenantUtil = customTenantUtil;
            this.lastActiveTime = System.currentTimeMillis();
            
            // 为小租户优化配置
            this.batchSize = 50;  // 小批次
            this.timeInterval = 3000; // 3秒超时
            
            // 创建专用调度器
            this.scheduler = Executors.newSingleThreadScheduledExecutor(
                r -> new Thread(r, "tenant-" + tenantId + "-batch-scheduler"));
        }

        /**
         * 添加数据到批处理队列
         */
        public void addData(T data) {
            synchronized (lock) {
                buffer.add(data);
                lastActiveTime = System.currentTimeMillis();
                
                // 双重触发机制
                if (buffer.size() >= batchSize) {
                    // 数量触发：达到批次大小立即处理
                    log.debug("Tenant {} batch triggered by size: {}", tenantId, buffer.size());
                    processBatch();
                } else if (currentTimer == null || currentTimer.isDone()) {
                    // 时间触发：启动定时器
                    log.debug("Tenant {} batch timer started", tenantId);
                    currentTimer = scheduler.schedule(
                        this::processBatch, timeInterval, TimeUnit.MILLISECONDS);
                }
            }
        }
        
        /**
         * 处理批次数据
         */
        private void processBatch() {
            synchronized (lock) {
                if (buffer.isEmpty()) return;
                
                // 获取当前批次数据
                List<T> batch = new ArrayList<>(buffer);
                buffer.clear();
                
                // 取消当前定时器
                if (currentTimer != null && !currentTimer.isDone()) {
                    currentTimer.cancel(false);
                    currentTimer = null;
                }
                
                // 使用共享线程池异步处理
                CompletableFuture.runAsync(() -> {
                    processData(batch);
                }, tenantResourceManager.getSharedThreadPool());
            }
        }
        
        /**
         * 实际数据处理逻辑
         */
        private void processData(List<T> data) {
            try {
                lastActiveTime = System.currentTimeMillis();
                // 关键：切换到租户数据库
                customTenantUtil.checkOutTenant(tenantId);
                // 执行实际的业务处理
                executeBatchOperation(data);
            } catch (Exception e) {
                log.error("Error processing batch for tenant " + tenantId, e);
                // 可以添加重试机制或死信队列处理
            }
        }
        
        /**
         * 执行批量数据库操作
         */
        private void executeBatchOperation(List<T> data) {
            try {
                // 批量插入或更新操作

                
            } catch (Exception e) {
                log.error("Database operation failed for tenant " + tenantId, e);
                throw new RuntimeException("Batch operation failed", e);
            }
        }
        /**
         * 清理资源
         */
        public void cleanup() {
            if (currentTimer != null && !currentTimer.isDone()) {
                currentTimer.cancel(true);
            }
            scheduler.shutdown();
            buffer.clear();
        }
    }
}
