package org.dromara.ai.config;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

/**
 * AI配置管理服务
 * 支持动态配置和热更新
 *
 * @author pengles
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AiConfigurationManager {

    private final ApplicationEventPublisher eventPublisher;
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);

    // 配置存储
    private final Map<String, AiConfiguration> configurations = new ConcurrentHashMap<>();

    // 配置监听器
    private final Map<String, Consumer<AiConfiguration>> configListeners = new ConcurrentHashMap<>();

    // 配置版本
    private final Map<String, Long> configVersions = new ConcurrentHashMap<>();

    // 配置历史
    private final Map<String, Map<Long, AiConfiguration>> configHistory = new ConcurrentHashMap<>();

    /**
     * AI配置类
     */
    public static class AiConfiguration {
        private String key;
        private Object value;
        private String description;
        private ConfigType type;
        private boolean hotReloadable;
        private LocalDateTime createTime;
        private LocalDateTime updateTime;
        private String updatedBy;
        private Map<String, Object> metadata;

        // Getters and Setters
        public String getKey() {
            return key;
        }

        public AiConfiguration setKey(String key) {
            this.key = key;
            return this;
        }

        public Object getValue() {
            return value;
        }

        public AiConfiguration setValue(Object value) {
            this.value = value;
            return this;
        }

        public String getDescription() {
            return description;
        }

        public AiConfiguration setDescription(String description) {
            this.description = description;
            return this;
        }

        public ConfigType getType() {
            return type;
        }

        public AiConfiguration setType(ConfigType type) {
            this.type = type;
            return this;
        }

        public boolean isHotReloadable() {
            return hotReloadable;
        }

        public AiConfiguration setHotReloadable(boolean hotReloadable) {
            this.hotReloadable = hotReloadable;
            return this;
        }

        public LocalDateTime getCreateTime() {
            return createTime;
        }

        public AiConfiguration setCreateTime(LocalDateTime createTime) {
            this.createTime = createTime;
            return this;
        }

        public LocalDateTime getUpdateTime() {
            return updateTime;
        }

        public AiConfiguration setUpdateTime(LocalDateTime updateTime) {
            this.updateTime = updateTime;
            return this;
        }

        public String getUpdatedBy() {
            return updatedBy;
        }

        public AiConfiguration setUpdatedBy(String updatedBy) {
            this.updatedBy = updatedBy;
            return this;
        }

        public Map<String, Object> getMetadata() {
            return metadata;
        }

        public AiConfiguration setMetadata(Map<String, Object> metadata) {
            this.metadata = metadata;
            return this;
        }
    }

    /**
     * 配置类型枚举
     */
    public enum ConfigType {
        PROVIDER_CONFIG,    // Provider配置
        MODEL_CONFIG,       // 模型配置
        SECURITY_CONFIG,    // 安全配置
        MONITOR_CONFIG,     // 监控配置
        SYSTEM_CONFIG       // 系统配置
    }

    /**
     * 配置变更事件
     */
    public static class ConfigChangeEvent {
        private String key;
        private Object oldValue;
        private Object newValue;
        private ConfigType type;
        private LocalDateTime changeTime;
        private String changedBy;

        public ConfigChangeEvent(String key, Object oldValue, Object newValue, ConfigType type, String changedBy) {
            this.key = key;
            this.oldValue = oldValue;
            this.newValue = newValue;
            this.type = type;
            this.changeTime = LocalDateTime.now();
            this.changedBy = changedBy;
        }

        // Getters
        public String getKey() {
            return key;
        }

        public Object getOldValue() {
            return oldValue;
        }

        public Object getNewValue() {
            return newValue;
        }

        public ConfigType getType() {
            return type;
        }

        public LocalDateTime getChangeTime() {
            return changeTime;
        }

        public String getChangedBy() {
            return changedBy;
        }
    }

    /**
     * 应用启动后初始化
     */
    @EventListener(ApplicationReadyEvent.class)
    public void initialize() {
        log.info("初始化AI配置管理器");

        // 加载默认配置
        loadDefaultConfigurations();

        // 启动配置监控
        startConfigMonitoring();

        log.info("AI配置管理器初始化完成，已加载{}个配置项", configurations.size());
    }

    /**
     * 获取配置
     *
     * @param key 配置键
     * @return 配置值
     */
    @SuppressWarnings("unchecked")
    public <T> T getConfig(String key) {
        AiConfiguration config = configurations.get(key);
        return config != null ? (T) config.getValue() : null;
    }

    /**
     * 获取配置（带默认值）
     *
     * @param key          配置键
     * @param defaultValue 默认值
     * @return 配置值
     */
    @SuppressWarnings("unchecked")
    public <T> T getConfig(String key, T defaultValue) {
        AiConfiguration config = configurations.get(key);
        return config != null ? (T) config.getValue() : defaultValue;
    }

    /**
     * 设置配置
     *
     * @param key       配置键
     * @param value     配置值
     * @param type      配置类型
     * @param updatedBy 更新者
     */
    public void setConfig(String key, Object value, ConfigType type, String updatedBy) {
        setConfig(key, value, type, true, null, updatedBy);
    }

    /**
     * 设置配置（完整参数）
     *
     * @param key           配置键
     * @param value         配置值
     * @param type          配置类型
     * @param hotReloadable 是否支持热更新
     * @param description   配置描述
     * @param updatedBy     更新者
     */
    public void setConfig(String key, Object value, ConfigType type, boolean hotReloadable,
                          String description, String updatedBy) {
        AiConfiguration oldConfig = configurations.get(key);
        Object oldValue = oldConfig != null ? oldConfig.getValue() : null;

        AiConfiguration newConfig = new AiConfiguration()
                .setKey(key)
                .setValue(value)
                .setType(type)
                .setHotReloadable(hotReloadable)
                .setDescription(description)
                .setUpdatedBy(updatedBy)
                .setUpdateTime(LocalDateTime.now());

        if (oldConfig == null) {
            newConfig.setCreateTime(LocalDateTime.now());
        } else {
            newConfig.setCreateTime(oldConfig.getCreateTime());
        }

        configurations.put(key, newConfig);

        // 更新版本
        long newVersion = configVersions.getOrDefault(key, 0L) + 1;
        configVersions.put(key, newVersion);

        // 保存历史
        configHistory.computeIfAbsent(key, k -> new ConcurrentHashMap<>())
                .put(newVersion, newConfig);

        // 触发配置变更事件
        ConfigChangeEvent event = new ConfigChangeEvent(key, oldValue, value, type, updatedBy);
        eventPublisher.publishEvent(event);

        // 通知监听器
        Consumer<AiConfiguration> listener = configListeners.get(key);
        if (listener != null && hotReloadable) {
            try {
                listener.accept(newConfig);
                log.info("配置热更新成功: {} = {}", key, value);
            } catch (Exception e) {
                log.error("配置热更新失败: {}", key, e);
            }
        }

        log.info("配置已更新: {} = {} (版本: {})", key, value, newVersion);
    }

    /**
     * 删除配置
     *
     * @param key       配置键
     * @param updatedBy 操作者
     */
    public void removeConfig(String key, String updatedBy) {
        AiConfiguration config = configurations.remove(key);
        if (config != null) {
            // 触发配置变更事件
            ConfigChangeEvent event = new ConfigChangeEvent(key, config.getValue(), null, config.getType(), updatedBy);
            eventPublisher.publishEvent(event);

            log.info("配置已删除: {}", key);
        }
    }

    /**
     * 注册配置监听器
     *
     * @param key      配置键
     * @param listener 监听器
     */
    public void addConfigListener(String key, Consumer<AiConfiguration> listener) {
        configListeners.put(key, listener);
        log.debug("已注册配置监听器: {}", key);
    }

    /**
     * 移除配置监听器
     *
     * @param key 配置键
     */
    public void removeConfigListener(String key) {
        configListeners.remove(key);
        log.debug("已移除配置监听器: {}", key);
    }

    /**
     * 获取所有配置
     *
     * @return 配置映射
     */
    public Map<String, AiConfiguration> getAllConfigurations() {
        return new ConcurrentHashMap<>(configurations);
    }

    /**
     * 获取指定类型的配置
     *
     * @param type 配置类型
     * @return 配置映射
     */
    public Map<String, AiConfiguration> getConfigurationsByType(ConfigType type) {
        Map<String, AiConfiguration> result = new ConcurrentHashMap<>();
        configurations.forEach((key, config) -> {
            if (config.getType() == type) {
                result.put(key, config);
            }
        });
        return result;
    }

    /**
     * 获取配置历史
     *
     * @param key 配置键
     * @return 配置历史
     */
    public Map<Long, AiConfiguration> getConfigHistory(String key) {
        return configHistory.getOrDefault(key, new ConcurrentHashMap<>());
    }

    /**
     * 回滚配置到指定版本
     *
     * @param key       配置键
     * @param version   版本号
     * @param updatedBy 操作者
     */
    public void rollbackConfig(String key, long version, String updatedBy) {
        Map<Long, AiConfiguration> history = configHistory.get(key);
        if (history == null || !history.containsKey(version)) {
            throw new IllegalArgumentException("配置版本不存在: " + key + " v" + version);
        }

        AiConfiguration historicalConfig = history.get(version);
        setConfig(key, historicalConfig.getValue(), historicalConfig.getType(),
                historicalConfig.isHotReloadable(), historicalConfig.getDescription(), updatedBy);

        log.info("配置已回滚: {} 到版本 {}", key, version);
    }

    /**
     * 重新加载所有配置
     */
    public void reloadAllConfigurations() {
        log.info("开始重新加载所有配置");

        configurations.forEach((key, config) -> {
            if (config.isHotReloadable()) {
                Consumer<AiConfiguration> listener = configListeners.get(key);
                if (listener != null) {
                    try {
                        listener.accept(config);
                        log.debug("配置重新加载成功: {}", key);
                    } catch (Exception e) {
                        log.error("配置重新加载失败: {}", key, e);
                    }
                }
            }
        });

        log.info("所有配置重新加载完成");
    }

    /**
     * 加载默认配置
     */
    private void loadDefaultConfigurations() {
        // Provider配置
        setConfig("ai.provider.openai.enabled", true, ConfigType.PROVIDER_CONFIG, true,
                "OpenAI Provider启用状态", "system");
        setConfig("ai.provider.openai.timeout", 30000, ConfigType.PROVIDER_CONFIG, true,
                "OpenAI Provider超时时间(ms)", "system");
        setConfig("ai.provider.openai.retry.max", 3, ConfigType.PROVIDER_CONFIG, true,
                "OpenAI Provider最大重试次数", "system");

        // 模型配置
        setConfig("ai.model.default", "gpt-3.5-turbo", ConfigType.MODEL_CONFIG, true,
                "默认AI模型", "system");
        setConfig("ai.model.temperature.default", 0.7, ConfigType.MODEL_CONFIG, true,
                "默认温度参数", "system");
        setConfig("ai.model.max_tokens.default", 2048, ConfigType.MODEL_CONFIG, true,
                "默认最大token数", "system");

        // 安全配置
        setConfig("ai.security.content_filter.enabled", true, ConfigType.SECURITY_CONFIG, true,
                "内容过滤启用状态", "system");
        setConfig("ai.security.rate_limit.enabled", true, ConfigType.SECURITY_CONFIG, true,
                "速率限制启用状态", "system");
        setConfig("ai.security.rate_limit.requests_per_minute", 60, ConfigType.SECURITY_CONFIG, true,
                "每分钟请求限制", "system");

        // 监控配置
        setConfig("ai.monitor.enabled", true, ConfigType.MONITOR_CONFIG, true,
                "监控启用状态", "system");
        setConfig("ai.monitor.metrics.retention_days", 30, ConfigType.MONITOR_CONFIG, true,
                "监控数据保留天数", "system");
        setConfig("ai.monitor.health_check.interval", 60, ConfigType.MONITOR_CONFIG, true,
                "健康检查间隔(秒)", "system");

        // 系统配置
        setConfig("ai.system.thread_pool.core_size", 10, ConfigType.SYSTEM_CONFIG, true,
                "线程池核心大小", "system");
        setConfig("ai.system.thread_pool.max_size", 50, ConfigType.SYSTEM_CONFIG, true,
                "线程池最大大小", "system");
        setConfig("ai.system.cache.enabled", true, ConfigType.SYSTEM_CONFIG, true,
                "缓存启用状态", "system");
    }

    /**
     * 启动配置监控
     */
    private void startConfigMonitoring() {
        // 定期检查配置变更
        scheduler.scheduleWithFixedDelay(() -> {
            try {
                // 这里可以实现从外部数据源检查配置变更
                // 例如数据库、配置中心等
                log.debug("配置监控检查完成");
            } catch (Exception e) {
                log.error("配置监控检查失败", e);
            }
        }, 30, 30, TimeUnit.SECONDS);

        // 定期清理历史配置
        scheduler.scheduleWithFixedDelay(() -> {
            try {
                cleanupConfigHistory();
            } catch (Exception e) {
                log.error("配置历史清理失败", e);
            }
        }, 1, 24, TimeUnit.HOURS);
    }

    /**
     * 清理配置历史
     */
    private void cleanupConfigHistory() {
        int maxHistoryVersions = getConfig("ai.config.history.max_versions", 10);

        configHistory.forEach((key, history) -> {
            if (history.size() > maxHistoryVersions) {
                // 保留最新的版本
                history.entrySet().stream()
                        .sorted(Map.Entry.<Long, AiConfiguration>comparingByKey().reversed())
                        .skip(maxHistoryVersions)
                        .map(Map.Entry::getKey)
                        .forEach(history::remove);
            }
        });

        log.debug("配置历史清理完成");
    }

    /**
     * 销毁资源
     */
    public void destroy() {
        if (scheduler != null && !scheduler.isShutdown()) {
            scheduler.shutdown();
            try {
                if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
                    scheduler.shutdownNow();
                }
            } catch (InterruptedException e) {
                scheduler.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
        log.info("AI配置管理器已销毁");
    }
}