using System;
using System.IO;
using System.Reflection;
using Tomlyn;
using Tomlyn.Model;
using Tomlyn.Syntax;

namespace NavisworksTransport.Core.Config
{
    /// <summary>
    /// 系统配置管理器
    /// 负责 TOML 配置文件的读取、保存和管理
    /// </summary>
    public class ConfigManager
    {
        private static ConfigManager _instance;
        private static readonly object _lock = new object();

        /// <summary>
        /// 单例实例
        /// </summary>
        public static ConfigManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_lock)
                    {
                        if (_instance == null)
                        {
                            _instance = new ConfigManager();
                        }
                    }
                }
                return _instance;
            }
        }

        /// <summary>
        /// 配置文件路径
        /// </summary>
        public static string ConfigFilePath
        {
            get
            {
                return Path.Combine(
                    Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
                    "Autodesk",
                    "Navisworks Manage 2026",
                    "plugins",
                    "NavisworksTransportPlugin",
                    "config.toml"
                );
            }
        }

        /// <summary>
        /// 配置目录
        /// </summary>
        public static string ConfigDirectory
        {
            get { return Path.GetDirectoryName(ConfigFilePath); }
        }

        /// <summary>
        /// 配置模板文件路径
        /// </summary>
        private static string ConfigTemplatePath
        {
            get
            {
                // 从插件当前目录获取模板文件
                var pluginDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                return Path.Combine(pluginDirectory, "default_config.toml");
            }
        }

        private SystemConfig _currentConfig;
        private string _cachedTemplateContent;

        private ConfigManager()
        {
            _currentConfig = LoadConfigFile();
        }

        /// <summary>
        /// 获取当前配置
        /// </summary>
        public SystemConfig Current
        {
            get { return _currentConfig; }
        }

        /// <summary>
        /// 读取配置模板文件内容
        /// </summary>
        private string ReadConfigTemplate()
        {
            if (!File.Exists(ConfigTemplatePath))
            {
                throw new FileNotFoundException($"配置模板文件不存在: {ConfigTemplatePath}");
            }

            LogManager.Info($"使用配置模板文件: {ConfigTemplatePath}");
            return File.ReadAllText(ConfigTemplatePath);
        }

        /// <summary>
        /// 加载配置文件，如果不存在则从模板创建
        /// </summary>
        private SystemConfig LoadConfigFile()
        {
            try
            {
                if (!File.Exists(ConfigFilePath))
                {
                    LogManager.Info($"配置文件不存在，从模板创建: {ConfigFilePath}");
                    var templateContent = ReadConfigTemplate();
                    WriteConfigFileDirect(templateContent);
                    return ParseTomlToConfig(templateContent);
                }

                LogManager.Info($"加载配置文件: {ConfigFilePath}");
                var tomlContent = File.ReadAllText(ConfigFilePath);
                var config = ParseTomlToConfig(tomlContent);

                LogManager.Info("配置文件加载成功");
                return config;
            }
            catch (Exception ex)
            {
                LogManager.Error($"加载配置文件失败: {ex.Message}");
                LogManager.Error($"堆栈跟踪: {ex.StackTrace}");

                // 加载失败时使用模板中的默认配置
                LogManager.Info("使用模板中的默认配置");
                var templateContent = ReadConfigTemplate();
                return ParseTomlToConfig(templateContent);
            }
        }

        /// <summary>
        /// 将 TOML 字符串解析为配置对象
        /// </summary>
        private SystemConfig ParseTomlToConfig(string tomlContent)
        {
            var model = Toml.ToModel(tomlContent);
            var config = CreateEmptyConfigObject();

            // 加载路径编辑配置
            if (!model.ContainsKey("path_editing"))
            {
                throw new InvalidOperationException("配置文件缺少 [path_editing] 部分");
            }

            var pathEdit = model["path_editing"] as TomlTable;
            if (pathEdit == null)
            {
                throw new InvalidOperationException("[path_editing] 部分格式错误");
            }

            config.PathEditing.CellSizeMeters = GetRequiredDoubleValue(pathEdit, "cell_size_meters");
            config.PathEditing.MaxHeightDiffMeters = GetRequiredDoubleValue(pathEdit, "max_height_diff_meters");
            config.PathEditing.VehicleLengthMeters = GetRequiredDoubleValue(pathEdit, "vehicle_length_meters");
            config.PathEditing.VehicleWidthMeters = GetRequiredDoubleValue(pathEdit, "vehicle_width_meters");
            config.PathEditing.VehicleHeightMeters = GetRequiredDoubleValue(pathEdit, "vehicle_height_meters");
            config.PathEditing.SafetyMarginMeters = GetRequiredDoubleValue(pathEdit, "safety_margin_meters");
            config.PathEditing.DefaultPathTurnRadius = GetRequiredDoubleValue(pathEdit, "default_path_turn_radius");
            config.PathEditing.ArcSamplingStep = GetRequiredDoubleValue(pathEdit, "arc_sampling_step");

            // 加载可视化配置
            if (!model.ContainsKey("visualization"))
            {
                throw new InvalidOperationException("配置文件缺少 [visualization] 部分");
            }

            var visual = model["visualization"] as TomlTable;
            if (visual == null)
            {
                throw new InvalidOperationException("[visualization] 部分格式错误");
            }

            config.Visualization.MarginRatio = GetRequiredDoubleValue(visual, "margin_ratio");

            // 加载动画配置
            if (!model.ContainsKey("animation"))
            {
                throw new InvalidOperationException("配置文件缺少 [animation] 部分");
            }

            var anim = model["animation"] as TomlTable;
            if (anim == null)
            {
                throw new InvalidOperationException("[animation] 部分格式错误");
            }

            config.Animation.FrameRate = GetRequiredIntValue(anim, "frame_rate");
            config.Animation.DurationSeconds = GetRequiredDoubleValue(anim, "duration_seconds");
            config.Animation.DetectionGapMeters = GetRequiredDoubleValue(anim, "detection_gap_meters");

            // 加载物流属性配置
            if (!model.ContainsKey("logistics"))
            {
                throw new InvalidOperationException("配置文件缺少 [logistics] 部分");
            }

            var logistics = model["logistics"] as TomlTable;
            if (logistics == null)
            {
                throw new InvalidOperationException("[logistics] 部分格式错误");
            }

            config.Logistics.Traversable = GetRequiredBoolValue(logistics, "traversable");
            config.Logistics.Priority = GetRequiredIntValue(logistics, "priority");
            config.Logistics.HeightLimitMeters = GetRequiredDoubleValue(logistics, "height_limit_meters");
            config.Logistics.SpeedLimitMetersPerSecond = GetRequiredDoubleValue(logistics, "speed_limit_meters_per_second");
            config.Logistics.WidthLimitMeters = GetRequiredDoubleValue(logistics, "width_limit_meters");

            return config;
        }

        /// <summary>
        /// 创建空的配置对象（初始化所有嵌套对象）
        /// </summary>
        private SystemConfig CreateEmptyConfigObject()
        {
            return new SystemConfig
            {
                GridGeneration = new GridGenerationConfig(),
                PathPlanning = new PathPlanningConfig(),
                PathEditing = new PathEditingConfig(),
                Visualization = new VisualizationConfig(),
                Animation = new AnimationConfig(),
                Logistics = new LogisticsConfig()
            };
        }

        /// <summary>
        /// 保存配置到文件
        /// </summary>
        public void SaveConfig(SystemConfig config)
        {
            try
            {
                // 确保目录存在
                Directory.CreateDirectory(ConfigDirectory);

                var tomlContent = GenerateTomlFromConfig(config);
                File.WriteAllText(ConfigFilePath, tomlContent);

                _currentConfig = config;
                LogManager.Info($"配置文件已保存: {ConfigFilePath}");
            }
            catch (Exception ex)
            {
                LogManager.Error($"保存配置文件失败: {ex.Message}");
                LogManager.Error($"堆栈跟踪: {ex.StackTrace}");
                throw;
            }
        }

        /// <summary>
        /// 直接写入配置文件内容（不经过模板转换）
        /// </summary>
        private void WriteConfigFileDirect(string tomlContent)
        {
            try
            {
                // 确保目录存在
                Directory.CreateDirectory(ConfigDirectory);

                File.WriteAllText(ConfigFilePath, tomlContent);
                LogManager.Info($"配置文件已创建: {ConfigFilePath}");
            }
            catch (Exception ex)
            {
                LogManager.Error($"写入配置文件失败: {ex.Message}");
                LogManager.Error($"堆栈跟踪: {ex.StackTrace}");
                throw;
            }
        }

        /// <summary>
        /// 从配置对象生成 TOML 字符串（使用模板格式）
        /// </summary>
        private string GenerateTomlFromConfig(SystemConfig config)
        {
            // 加载模板内容（缓存）
            if (_cachedTemplateContent == null)
            {
                _cachedTemplateContent = ReadConfigTemplate();
            }

            // 解析模板
            var syntax = Toml.Parse(_cachedTemplateContent);
            var model = syntax.ToModel();

            // 更新配置值到模型
            ApplyConfigValuesToModel(model, config);

            // 转换回 TOML 字符串
            return Toml.FromModel(model);
        }

        /// <summary>
        /// 将配置对象的值应用到 TOML 模型
        /// </summary>
        private void ApplyConfigValuesToModel(TomlTable model, SystemConfig config)
        {
            // 更新路径编辑配置
            if (model.ContainsKey("path_editing"))
            {
                var pathEdit = model["path_editing"] as TomlTable;
                if (pathEdit != null)
                {
                    pathEdit["cell_size_meters"] = config.PathEditing.CellSizeMeters;
                    pathEdit["max_height_diff_meters"] = config.PathEditing.MaxHeightDiffMeters;
                    pathEdit["vehicle_length_meters"] = config.PathEditing.VehicleLengthMeters;
                    pathEdit["vehicle_width_meters"] = config.PathEditing.VehicleWidthMeters;
                    pathEdit["vehicle_height_meters"] = config.PathEditing.VehicleHeightMeters;
                    pathEdit["safety_margin_meters"] = config.PathEditing.SafetyMarginMeters;
                    pathEdit["default_path_turn_radius"] = config.PathEditing.DefaultPathTurnRadius;
                    pathEdit["arc_sampling_step"] = config.PathEditing.ArcSamplingStep;
                }
            }

            // 更新可视化配置
            if (model.ContainsKey("visualization"))
            {
                var visual = model["visualization"] as TomlTable;
                if (visual != null)
                {
                    visual["margin_ratio"] = config.Visualization.MarginRatio;
                }
            }

            // 更新动画配置
            if (model.ContainsKey("animation"))
            {
                var anim = model["animation"] as TomlTable;
                if (anim != null)
                {
                    anim["frame_rate"] = config.Animation.FrameRate;
                    anim["duration_seconds"] = config.Animation.DurationSeconds;
                    anim["detection_gap_meters"] = config.Animation.DetectionGapMeters;
                }
            }

            // 更新物流属性配置
            if (model.ContainsKey("logistics"))
            {
                var logistics = model["logistics"] as TomlTable;
                if (logistics != null)
                {
                    logistics["traversable"] = config.Logistics.Traversable;
                    logistics["priority"] = config.Logistics.Priority;
                    logistics["height_limit_meters"] = config.Logistics.HeightLimitMeters;
                    logistics["speed_limit_meters_per_second"] = config.Logistics.SpeedLimitMetersPerSecond;
                    logistics["width_limit_meters"] = config.Logistics.WidthLimitMeters;
                }
            }
        }

        /// <summary>
        /// 重新加载配置文件
        /// </summary>
        public void Reload()
        {
            _currentConfig = LoadConfigFile();
        }

        /// <summary>
        /// 恢复为模板中的默认配置
        /// </summary>
        public void RestoreToDefaults()
        {
            LogManager.Info("开始恢复默认配置...");
            var templateContent = ReadConfigTemplate();
            LogManager.Info($"模板内容长度: {templateContent.Length}");
            LogManager.Info($"模板内容前200字符: {templateContent.Substring(0, Math.Min(200, templateContent.Length))}");
            
            WriteConfigFileDirect(templateContent);
            
            var newConfig = ParseTomlToConfig(templateContent);
            LogManager.Info($"解析后的配置 - CellSizeMeters: {newConfig.PathEditing.CellSizeMeters}");
            LogManager.Info($"解析后的配置 - VehicleLengthMeters: {newConfig.PathEditing.VehicleLengthMeters}");
            
            _currentConfig = newConfig;
            LogManager.Info("默认配置恢复完成");
        }

        // 辅助方法：从 TomlTable 获取必需值
        private double GetRequiredDoubleValue(TomlTable table, string key)
        {
            if (!table.ContainsKey(key))
            {
                throw new InvalidOperationException($"配置项 '{key}' 不存在");
            }

            var value = table[key];
            if (value is long longValue)
                return (double)longValue;
            if (value is double doubleValue)
                return doubleValue;

            throw new InvalidOperationException($"配置项 '{key}' 的类型错误，应为数值类型");
        }

        private int GetRequiredIntValue(TomlTable table, string key)
        {
            if (!table.ContainsKey(key))
            {
                throw new InvalidOperationException($"配置项 '{key}' 不存在");
            }

            var value = table[key];
            if (value is long longValue)
                return (int)longValue;

            throw new InvalidOperationException($"配置项 '{key}' 的类型错误，应为整数类型");
        }

        private bool GetRequiredBoolValue(TomlTable table, string key)
        {
            if (!table.ContainsKey(key))
            {
                throw new InvalidOperationException($"配置项 '{key}' 不存在");
            }

            var value = table[key];
            if (value is bool boolValue)
                return boolValue;

            throw new InvalidOperationException($"配置项 '{key}' 的类型错误，应为布尔类型");
        }
    }
}
