package com.playerblocklife;

import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

/**
 * 配置管理器 - 负责加载、保存和管理插件的配置文件
 * 
 * <p>主要功能包括：
 * <ul>
 *   <li>加载和验证配置文件</li>
 *   <li>配置版本检查和自动更新</li>
 *   <li>提供类型安全的配置项访问方法</li>
 *   <li>处理配置文件的保存和重载</li>
 *   <li>管理SkinsRestorer插件集成配置</li>
 *   <li>支持多种皮肤来源的优先级配置</li>
 * </ul>
 * 
 * <p><b>SkinsRestorer配置支持：</b></p>
 * <ul>
 *   <li><code>skin.source</code>：皮肤来源优先级（skinsrestorer/player_profile/local_cache）</li>
 *   <li><code>skin.use-skinsrestorer</code>：是否启用SkinsRestorer支持</li>
 *   <li><code>skin.cache.expire_days</code>：皮肤缓存过期时间</li>
 *   <li>默认配置已优化，优先使用SkinsRestorer以支持离线服务器</li>
 * </ul>
 * 
 * @author xiaobai
 * @version 2.2.0-1.20.4
 * @since 1.0.0
 */
public class ConfigManager {
    private final PlayerBlockLife plugin;
    private FileConfiguration config;
    private File configFile;

    /**
     * 构造一个新的配置管理器
     * 
     * @param plugin 插件主类实例，用于访问插件相关功能
     */
    public ConfigManager(PlayerBlockLife plugin) {
        this.plugin = plugin;
        this.configFile = new File(plugin.getDataFolder(), "config.yml");
    }

    /**
     * 加载插件配置
     * 
     * <p>执行以下操作：
     * <ol>
     *   <li>确保插件数据文件夹存在</li>
     *   <li>如果配置文件不存在，从JAR中复制默认配置</li>
     *   <li>调用reloadConfig()重新加载配置</li>
     * </ol>
     * 
     * @see #reloadConfig()
     */
    public void loadConfig() {
        // 确保配置文件夹存在
        if (!plugin.getDataFolder().exists()) {
            plugin.getDataFolder().mkdirs();
        }

        // 如果配置文件不存在，从JAR中复制默认配置
        if (!configFile.exists()) {
            plugin.saveDefaultConfig();
            plugin.logInfo("创建默认配置文件");
        }

        // 重新加载配置
        reloadConfig();
    }

    /**
     * 重新加载配置文件
     * 
     * <p>执行以下操作：
     * <ol>
     *   <li>从磁盘重新加载配置文件</li>
     *   <li>加载JAR中的默认配置作为后备</li>
     *   <li>检查配置版本并进行必要的更新</li>
     * </ol>
     * 
     * @see #checkConfigVersion()
     */
    public void reloadConfig() {
        // 重新从磁盘加载配置
        config = YamlConfiguration.loadConfiguration(configFile);

        // 加载默认配置作为后备
        InputStream defaultConfigStream = plugin.getResource("config.yml");
        if (defaultConfigStream != null) {
            YamlConfiguration defaultConfig = YamlConfiguration.loadConfiguration(
                    new InputStreamReader(defaultConfigStream, StandardCharsets.UTF_8));
            config.setDefaults(defaultConfig);
        }

        // 检查配置版本，如果需要则更新
        checkConfigVersion();

        plugin.logInfo("配置已加载");
    }

    /**
     * 检查配置版本并更新
     */
    private void checkConfigVersion() {
        int currentVersion = config.getInt("config-version", 1);
        int latestVersion = 1; // 最新配置版本

        if (currentVersion < latestVersion) {
            plugin.logWarning("检测到旧版配置文件，正在更新...");
            updateConfig(currentVersion, latestVersion);
        }
    }

    /**
     * 更新配置文件
     */
    private void updateConfig(int fromVersion, int toVersion) {
        if (fromVersion == 1 && toVersion == 2) {
            // 添加命令启用配置
            if (!config.contains("commands.setlifeblocks.enabled")) {
                config.set("commands.setlifeblocks.enabled", true);
                config.set("commands.setlifeblocks.allow_self_use", true);
                config.set("commands.setlifeblocks.allow_admin_use", true);
                
                config.set("commands.checklifeblocks.enabled", true);
                config.set("commands.checklifeblocks.allow_self_use", true);
                config.set("commands.checklifeblocks.allow_admin_use", true);
                
                config.set("commands.pblreload.enabled", true);
                config.set("commands.pblreload.admin_only", true);
                
                config.set("commands.pbldelete.enabled", true);
                config.set("commands.pbldelete.admin_only", true);
                
                config.set("commands.pblrevive.enabled", true);
                config.set("commands.pblrevive.admin_only", true);
                
                config.set("commands.pblstats.enabled", true);
                config.set("commands.pblstats.admin_only", true);
            }
            
            // 更新消息配置
            if (!config.contains("messages.use_external_file")) {
                config.set("messages.use_external_file", true);
                config.set("messages.external_file", "messages.yml");
            }

            // 更新版本号
            config.set("config-version", toVersion);

            try {
                config.save(configFile);
                plugin.logInfo("配置文件已更新到版本 " + toVersion);
            } catch (IOException e) {
                plugin.logError("保存更新后的配置文件失败", e);
            }
        }
    }

    /**
     * 保存当前配置到文件
     * 
     * <p>将内存中的配置数据写入到config.yml文件中。
     * 如果保存失败，会记录错误日志。</p>
     * 
     * @throws IOException 如果文件写入失败
     */
    public void saveConfig() {
        try {
            config.save(configFile);
        } catch (IOException e) {
            plugin.logError("保存配置文件失败", e);
        }
    }

    /**
     * 获取配置对象
     * 
     * <p>如果配置对象为null，会自动调用reloadConfig()加载配置。</p>
     * 
     * @return 当前的FileConfiguration配置对象
     * @see #reloadConfig()
     */
    public FileConfiguration getConfig() {
        if (config == null) {
            reloadConfig();
        }
        return config;
    }

    /**
     * 检查玩家方块被挖光时是否死亡
     * 
     * @return 如果玩家方块被挖光时死亡则返回true，否则返回false
     */
    public boolean isDieWhenBlocksGone() {
        return getConfig().getBoolean("game.die_when_blocks_gone", true);
    }

    /**
     * 检查玩家死亡后是否成为观察者
     * 
     * @return 如果玩家死亡后成为观察者则返回true，否则返回false
     */
    public boolean isBecomeSpectator() {
        return getConfig().getBoolean("game.become_spectator", true);
    }

    /**
     * 检查是否启用生命值系统
     * 
     * @return 如果启用生命值系统则返回true，否则返回false
     */
    public boolean isHealthSystemEnabled() {
        return getConfig().getBoolean("game.health_system", true);
    }

    /**
     * 检查是否启用自动保存
     * 
     * @return 如果启用自动保存则返回true，否则返回false
     */
    public boolean isAutoSaveEnabled() {
        return getConfig().getBoolean("storage.auto_save.enabled", true);
    }

    /**
     * 获取自动保存间隔
     * 
     * @return 自动保存间隔（秒），默认为300秒（5分钟）
     */
    public int getAutoSaveInterval() {
        return getConfig().getInt("storage.auto_save.interval", 300);
    }

    /**
     * 获取存储类型配置
     * 
     * @return 存储类型配置值，默认为"yaml"
     */
    public String getStorageType() {
        return getConfig().getString("storage.type", "yaml");
    }

    /**
     * 检查是否在方块被破坏时广播消息
     * 
     * @return 如果在方块被破坏时广播消息则返回true，否则返回false
     */
    public boolean isBroadcastOnBlockBreak() {
        return getConfig().getBoolean("game.broadcast.on_block_break", true);
    }

    /**
     * 检查是否在玩家死亡时广播消息
     * 
     * @return 如果在玩家死亡时广播消息则返回true，否则返回false
     */
    public boolean isBroadcastOnPlayerDeath() {
        return getConfig().getBoolean("game.broadcast.on_player_death", true);
    }

    /**
     * 获取广播范围
     * 
     * @return 广播范围（方块），默认为30
     */
    public int getBroadcastRange() {
        return getConfig().getInt("game.broadcast.range", 30);
    }

    /**
     * 检查是否给予挖掘奖励经验
     * 
     * @return 如果给予挖掘奖励经验则返回true，否则返回false
     */
    public boolean isGiveExpReward() {
        return getConfig().getBoolean("game.break_rewards.give_exp", true);
    }

    /**
     * 获取奖励经验数量
     * 
     * @return 奖励经验数量，默认为5
     */
    public int getExpRewardAmount() {
        return getConfig().getInt("game.break_rewards.exp_amount", 5);
    }

    /**
     * 检查是否保护方块免受爆炸破坏
     * 
     * @return 如果保护方块免受爆炸破坏则返回true，否则返回false
     */
    public boolean isProtectFromExplosions() {
        return getConfig().getBoolean("protection.protect_from_explosions", true);
    }

    /**
     * 检查是否保护方块免受火灾破坏
     * 
     * @return 如果保护方块免受火灾破坏则返回true，否则返回false
     */
    public boolean isProtectFromFire() {
        return getConfig().getBoolean("protection.protect_from_fire", true);
    }

    /**
     * 检查是否保护方块免受活塞推动
     * 
     * @return 如果保护方块免受活塞推动则返回true，否则返回false
     */
    public boolean isProtectFromPistons() {
        return getConfig().getBoolean("protection.protect_from_pistons", true);
    }



    // 命令启用配置获取方法
    /**
     * 检查命令是否启用
     * 
     * @param commandName 命令名称
     * @return 如果命令启用则返回true，否则返回false
     */
    public boolean isCommandEnabled(String commandName) {
        return getConfig().getBoolean("commands." + commandName + ".enabled", true);
    }

    /**
     * 检查是否允许玩家自己使用命令
     * 
     * @param commandName 命令名称
     * @return 如果允许玩家自己使用命令则返回true，否则返回false
     */
    public boolean isSelfUseAllowed(String commandName) {
        return getConfig().getBoolean("commands." + commandName + ".allow_self_use", true);
    }

    /**
     * 检查是否允许管理员使用命令
     * 
     * @param commandName 命令名称
     * @return 如果允许管理员使用命令则返回true，否则返回false
     */
    public boolean isAdminUseAllowed(String commandName) {
        return getConfig().getBoolean("commands." + commandName + ".allow_admin_use", true);
    }

    /**
     * 检查命令是否仅管理员可用
     * 
     * @param commandName 命令名称
     * @return 如果命令仅管理员可用则返回true，否则返回false
     */
    public boolean isAdminOnly(String commandName) {
        return getConfig().getBoolean("commands." + commandName + ".admin_only", false);
    }

    // 消息文件配置获取方法
    /**
     * 检查是否使用外部消息文件
     * 
     * @return 如果使用外部消息文件则返回true，否则返回false
     */
    public boolean useExternalMessageFile() {
        return getConfig().getBoolean("messages.use_external_file", true);
    }

    /**
     * 获取外部消息文件名
     * 
     * @return 外部消息文件名，默认为"messages.yml"
     */
    public String getExternalMessageFileName() {
        return getConfig().getString("messages.external_file", "messages.yml");
    }

    /**
     * 获取消息
     * 
     * @param path 消息路径
     * @param defaultValue 默认值
     * @return 消息内容
     */
    public String getMessage(String path, String defaultValue) {
        // 优先从外部消息文件获取
        if (useExternalMessageFile()) {
            // 这里应该调用MessageManager来获取消息
            // 暂时返回默认值，MessageManager会处理具体逻辑
            return defaultValue;
        }
        
        // 从config.yml获取
        String message = getConfig().getString("messages." + path, defaultValue);
        if (message != null) {
            message = message.replace("&", "§");
        }
        return message;
    }
}