using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Text;
using System.Linq;
using System.Globalization;
using System.Web.Script.Serialization;

using Autodesk.Navisworks.Api;

namespace NavisworksTransport
{
    #region JSON数据模型类

    /// <summary>
    /// JSON格式的路径点数据
    /// </summary>
    public class JsonPathPoint
    {
        public string id { get; set; }
        public string name { get; set; }
        public string type { get; set; }
        public int index { get; set; }
        public double x { get; set; }
        public double y { get; set; }
        public double z { get; set; }
        public string created { get; set; }
    }

    /// <summary>
    /// JSON格式的物体限制数据
    /// </summary>
    public class JsonObjectLimits
    {
        public double maxLength { get; set; }
        public double maxWidth { get; set; }
        public double maxHeight { get; set; }
        public double safetyMargin { get; set; }
    }

    /// <summary>
    /// JSON格式的路径数据
    /// </summary>
    public class JsonPathRoute
    {
        public string id { get; set; }
        public string name { get; set; }
        public string description { get; set; }
        public string pathType { get; set; }
        public string railMountMode { get; set; }
        public string railPathDefinitionMode { get; set; }
        public double railNormalOffset { get; set; }
        public JsonVector3 railPreferredNormal { get; set; }
        public double totalLength { get; set; }
        public JsonObjectLimits objectLimits { get; set; }
        public double gridSize { get; set; }
        public double liftHeight { get; set; }
        public string created { get; set; }
        public JsonPathPoint[] points { get; set; }
    }

    public class JsonVector3
    {
        public double x { get; set; }
        public double y { get; set; }
        public double z { get; set; }
    }

    /// <summary>
    /// JSON格式的项目信息
    /// </summary>
    public class JsonProjectInfo
    {
        public string name { get; set; }
        public string description { get; set; }
        public string units { get; set; }
        public string coordinateSystem { get; set; }
    }

    /// <summary>
    /// JSON格式的路径规划数据根对象
    /// </summary>
    public class JsonPathPlanningData
    {
        public string version { get; set; }
        public string generator { get; set; }
        public string timestamp { get; set; }
        public JsonProjectInfo ProjectInfo { get; set; }
        public JsonPathRoute[] Routes { get; set; }
    }

    /// <summary>
    /// JSON格式的根对象
    /// </summary>
    public class JsonRootObject
    {
        public JsonPathPlanningData PathPlanningData { get; set; }
    }

    #endregion

    /// <summary>
    /// 路径数据管理器
    /// 负责路径数据的导入导出、持久化存储和DELMIA格式兼容
    /// </summary>
    public class PathDataManager
    {
        private const string DEFAULT_EXPORT_FOLDER = "PathPlanningExports";
        private const string DEFAULT_FILE_EXTENSION = ".xml";
        private const string JSON_FILE_EXTENSION = ".json";
        private const string CSV_FILE_EXTENSION = ".csv";

        // DELMIA兼容格式配置
        private readonly string _delmiaNamespace = "http://www.3ds.com/delmia/pathplanning";
        private readonly string _delmiaVersion = "1.0";

        /// <summary>
        /// 导出路径到XML文件（DELMIA兼容格式）
        /// </summary>
        /// <param name="routes">路径集合</param>
        /// <param name="filePath">文件路径</param>
        /// <param name="exportSettings">导出设置</param>
        /// <returns>是否成功</returns>
        public bool ExportToXml(List<PathRoute> routes, string filePath, ExportSettings exportSettings = null)
        {
            if (routes == null || routes.Count == 0)
            {
                throw new ArgumentException("路径集合不能为空");
            }

            try
            {
                LogManager.Info($"[路径文件操作] 开始导出 {routes.Count} 条路径到XML文件: {filePath}");
                // 确保导出目录存在
                var directory = Path.GetDirectoryName(filePath);
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }

                // 创建XML文档
                var xmlDoc = new XmlDocument();
                var declaration = xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", null);
                xmlDoc.AppendChild(declaration);

                // 创建根元素
                var rootElement = xmlDoc.CreateElement("PathPlanningData", _delmiaNamespace);
                rootElement.SetAttribute("version", _delmiaVersion);
                rootElement.SetAttribute("generator", "NavisworksTransport");
                rootElement.SetAttribute("timestamp", DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss"));
                xmlDoc.AppendChild(rootElement);

                // 添加项目信息
                var projectInfo = CreateProjectInfoElement(xmlDoc, exportSettings);
                rootElement.AppendChild(projectInfo);

                // 添加路径数据
                var routesElement = xmlDoc.CreateElement("Routes", _delmiaNamespace);
                rootElement.AppendChild(routesElement);

                foreach (var route in routes)
                {
                    if (route.IsValid())
                    {
                        var routeElement = CreateRouteElement(xmlDoc, route, exportSettings);
                        routesElement.AppendChild(routeElement);
                    }
                }

                // 保存文件
                using (var writer = new XmlTextWriter(filePath, Encoding.UTF8))
                {
                    writer.Formatting = Formatting.Indented;
                    writer.Indentation = 2;
                    xmlDoc.WriteTo(writer);
                }

                LogManager.Info($"[路径文件操作] 成功导出 {routes.Count} 条路径到XML文件: {filePath}");
                return true;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[路径文件操作] 导出XML文件失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 从XML文件导入路径
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns>路径集合</returns>
        public List<PathRoute> ImportFromXml(string filePath)
        {
            var routes = new List<PathRoute>();

            if (!File.Exists(filePath))
            {
                throw new FileNotFoundException($"文件不存在: {filePath}");
            }

            LogManager.Info($"[路径文件操作] 开始从XML文件导入路径: {filePath}");

            try
            {
                var xmlDoc = new XmlDocument();
                xmlDoc.Load(filePath);

                // 验证根元素
                var rootElement = xmlDoc.DocumentElement;
                if (rootElement?.Name != "PathPlanningData")
                {
                    throw new InvalidOperationException("无效的路径规划数据文件格式");
                }

                // 读取路径数据
                var routesElement = rootElement.SelectSingleNode("*[local-name()='Routes']");
                if (routesElement != null)
                {
                    foreach (XmlNode routeNode in routesElement.ChildNodes)
                    {
                        if (routeNode.NodeType == XmlNodeType.Element)
                        {
                            var route = ParseRouteElement(routeNode);
                            if (route != null && route.IsValid())
                            {
                                routes.Add(route);
                            }
                        }
                    }
                }

                LogManager.Info($"[路径文件操作] 成功从XML文件导入 {routes.Count} 条路径");
                return routes;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[路径文件操作] 导入XML文件失败: {ex.Message}", ex);
                throw;
            }
        }

        /// <summary>
        /// 导出路径到JSON文件
        /// </summary>
        /// <param name="routes">路径集合</param>
        /// <param name="filePath">文件路径</param>
        /// <param name="exportSettings">导出设置</param>
        /// <returns>是否成功</returns>
        public bool ExportToJson(List<PathRoute> routes, string filePath, ExportSettings exportSettings = null)
        {
            if (routes == null || routes.Count == 0)
            {
                throw new ArgumentException("路径集合不能为空");
            }

            try
            {
                LogManager.Info($"[路径文件操作] 开始导出 {routes.Count} 条路径到JSON文件: {filePath}");
                // 确保导出目录存在
                var directory = Path.GetDirectoryName(filePath);
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }

                // 创建JSON数据结构
                var jsonData = new
                {
                    PathPlanningData = new
                    {
                        version = _delmiaVersion,
                        generator = "NavisworksTransport",
                        timestamp = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss"),
                        ProjectInfo = new
                        {
                            name = exportSettings?.ProjectName ?? "NavisworksTransport路径规划",
                            description = exportSettings?.Description ?? "物流路径规划数据",
                            units = exportSettings?.Units ?? "meters",
                            coordinateSystem = exportSettings?.CoordinateSystem ?? "Global"
                        },
                        Routes = routes.Where(r => r.IsValid()).Select(route => new
                        {
                            id = route.Id,
                            name = route.Name,
                            description = route.Description ?? "",
                            pathType = route.PathType.ToString(),
                            railMountMode = route.RailMountMode.ToString(),
                            railPathDefinitionMode = route.RailPathDefinitionMode.ToString(),
                            railNormalOffset = Math.Round(route.RailNormalOffset, exportSettings?.Precision ?? 3),
                            railPreferredNormal = route.RailPreferredNormal != null ? new
                            {
                                x = Math.Round(route.RailPreferredNormal.X, exportSettings?.Precision ?? 3),
                                y = Math.Round(route.RailPreferredNormal.Y, exportSettings?.Precision ?? 3),
                                z = Math.Round(route.RailPreferredNormal.Z, exportSettings?.Precision ?? 3)
                            } : null,
                            totalLength = Math.Round(route.TotalLength, exportSettings?.Precision ?? 3),
                            objectLimits = new
                            {
                                maxLength = Math.Round(route.MaxObjectLength, exportSettings?.Precision ?? 3),
                                maxWidth = Math.Round(route.MaxObjectWidth, exportSettings?.Precision ?? 3),
                                maxHeight = Math.Round(route.MaxObjectHeight, exportSettings?.Precision ?? 3),
                                safetyMargin = Math.Round(route.SafetyMargin, exportSettings?.Precision ?? 3)
                            },
                            gridSize = Math.Round(route.GridSize, exportSettings?.Precision ?? 3),
                            liftHeight = Math.Round(route.LiftHeight, exportSettings?.Precision ?? 3),
                            created = route.CreatedTime.ToString("yyyy-MM-ddTHH:mm:ss"),
                            points = route.GetSortedPoints().Select(point => new
                            {
                                id = point.Id,
                                name = point.Name,
                                type = point.Type.ToString(),
                                index = point.Index,
                                x = Math.Round(point.Position.X, exportSettings?.Precision ?? 3),
                                y = Math.Round(point.Position.Y, exportSettings?.Precision ?? 3),
                                z = Math.Round(point.Position.Z, exportSettings?.Precision ?? 3),
                                created = point.CreatedTime.ToString("yyyy-MM-ddTHH:mm:ss")
                            }).ToArray(),
                            edges = route.Edges != null && route.Edges.Count > 0 ? route.Edges.Select(edge => new
                            {
                                type = edge.SegmentType.ToString().ToLower(),
                                physicalLength = Math.Round(edge.PhysicalLength, exportSettings?.Precision ?? 3),
                                trajectory = edge.SegmentType == PathSegmentType.Arc && edge.Trajectory != null ? new
                                {
                                    ts = new
                                    {
                                        x = Math.Round(edge.Trajectory.Ts.X, 3),
                                        y = Math.Round(edge.Trajectory.Ts.Y, 3),
                                        z = Math.Round(edge.Trajectory.Ts.Z, 3)
                                    },
                                    te = new
                                    {
                                        x = Math.Round(edge.Trajectory.Te.X, 3),
                                        y = Math.Round(edge.Trajectory.Te.Y, 3),
                                        z = Math.Round(edge.Trajectory.Te.Z, 3)
                                    },
                                    arcCenter = new
                                    {
                                        x = Math.Round(edge.Trajectory.ArcCenter.X, 3),
                                        y = Math.Round(edge.Trajectory.ArcCenter.Y, 3),
                                        z = Math.Round(edge.Trajectory.ArcCenter.Z, 3)
                                    },
                                    requestedRadius = Math.Round(edge.Trajectory.RequestedRadius, 3),
                                    actualRadius = Math.Round(edge.Trajectory.ActualRadius, 3),
                                    deflectionAngle = Math.Round(edge.Trajectory.DeflectionAngle, 3),
                                    arcLength = Math.Round(edge.Trajectory.ArcLength, 3)
                                } : null
                            }).ToArray() : null
                        }).ToArray()
                    }
                };

                // 序列化为JSON
                var serializer = new JavaScriptSerializer();
                var jsonString = serializer.Serialize(jsonData);
                
                // 格式化JSON输出（简单的美化）
                var formattedJson = FormatJsonString(jsonString);

                // 保存文件
                File.WriteAllText(filePath, formattedJson, Encoding.UTF8);

                LogManager.Info($"[路径文件操作] 成功导出 {routes.Count} 条路径到JSON文件: {filePath}");
                return true;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[路径文件操作] 导出JSON文件失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 导出路径到CSV文件
        /// </summary>
        /// <param name="routes">路径集合</param>
        /// <param name="filePath">文件路径</param>
        /// <param name="exportSettings">导出设置</param>
        /// <returns>是否成功</returns>
        public bool ExportToCsv(List<PathRoute> routes, string filePath, ExportSettings exportSettings = null)
        {
            if (routes == null || routes.Count == 0)
            {
                throw new ArgumentException("路径集合不能为空");
            }

            try
            {
                LogManager.Info($"[路径文件操作] 开始导出 {routes.Count} 条路径到CSV文件: {filePath}");
                // 确保导出目录存在
                var directory = Path.GetDirectoryName(filePath);
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }

                using (var writer = new StreamWriter(filePath, false, Encoding.UTF8))
                {
                    // 写入CSV表头（采样点格式）
                    writer.WriteLine("RouteId,EdgeIndex,SegmentType,PointIndex,X,Y,Z");

                    // 写入采样点数据行
                    foreach (var route in routes.Where(r => r.IsValid()))
                    {
                        if (route.Edges != null && route.Edges.Count > 0)
                        {
                            for (int edgeIndex = 0; edgeIndex < route.Edges.Count; edgeIndex++)
                            {
                                var edge = route.Edges[edgeIndex];

                                // 只导出已存在的采样点
                                if (edge.SampledPoints != null && edge.SampledPoints.Count > 0)
                                {
                                    for (int pointIndex = 0; pointIndex < edge.SampledPoints.Count; pointIndex++)
                                    {
                                        var point = edge.SampledPoints[pointIndex];
                                        var row = string.Join(",",
                                            EscapeCsvValue(route.Id),
                                            edgeIndex.ToString(),
                                            edge.SegmentType.ToString(),
                                            pointIndex.ToString(),
                                            point.X.ToString("F3", CultureInfo.InvariantCulture),
                                            point.Y.ToString("F3", CultureInfo.InvariantCulture),
                                            point.Z.ToString("F3", CultureInfo.InvariantCulture)
                                        );
                                        writer.WriteLine(row);
                                    }
                                }
                            }
                        }
                    }
                }

                LogManager.Info($"[路径文件操作] 成功导出路径到CSV文件: {filePath}");
                return true;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[路径文件操作] 导出CSV文件失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 从JSON文件导入路径
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns>路径集合</returns>
        public List<PathRoute> ImportFromJson(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                throw new ArgumentException("文件路径不能为空", nameof(filePath));
            }

            if (!File.Exists(filePath))
            {
                throw new FileNotFoundException($"找不到文件: {filePath}", filePath);
            }

            try
            {
                LogManager.Info($"[路径文件操作] 开始从JSON文件导入路径: {filePath}");

                // 读取JSON文件
                string jsonContent = File.ReadAllText(filePath, Encoding.UTF8);

                // 反序列化JSON数据
                var serializer = new JavaScriptSerializer();
                var rootObject = serializer.Deserialize<JsonRootObject>(jsonContent);

                if (rootObject?.PathPlanningData == null)
                {
                    throw new InvalidDataException("JSON文件格式不正确，缺少PathPlanningData节点");
                }

                var pathData = rootObject.PathPlanningData;
                var routes = new List<PathRoute>();

                if (pathData.Routes != null && pathData.Routes.Length > 0)
                {
                    LogManager.Info($"发现 {pathData.Routes.Length} 条路径，开始导入...");

                    foreach (var jsonRoute in pathData.Routes)
                    {
                        try
                        {
                            // 验证路径数据完整性
                            if (string.IsNullOrEmpty(jsonRoute.id) || string.IsNullOrEmpty(jsonRoute.name))
                            {
                                LogManager.Warning($"跳过无效路径：缺少必要字段 (id或name)");
                                continue;
                            }

                            if (jsonRoute.points == null || jsonRoute.points.Length == 0)
                            {
                                LogManager.Warning($"跳过空路径: {jsonRoute.name}，路径点数量为0");
                                continue;
                            }

                            // 创建路径对象
                            var route = new PathRoute(jsonRoute.name)
                            {
                                Id = jsonRoute.id,
                                Description = jsonRoute.description ?? "",
                                CreatedTime = ParseJsonDateTime(jsonRoute.created),
                                MaxObjectLength = jsonRoute.objectLimits?.maxLength ?? 0,
                                MaxObjectWidth = jsonRoute.objectLimits?.maxWidth ?? 0,
                                MaxObjectHeight = jsonRoute.objectLimits?.maxHeight ?? 0,
                                SafetyMargin = jsonRoute.objectLimits?.safetyMargin ?? 0,
                                GridSize = jsonRoute.gridSize,
                                LiftHeight = jsonRoute.liftHeight
                            };

                            // 🔥 解析路径类型（关键字段，不输则报错）
                            if (!string.IsNullOrEmpty(jsonRoute.pathType))
                            {
                                if (Enum.TryParse<PathType>(jsonRoute.pathType, out var pathType))
                                {
                                    route.PathType = pathType;
                                }
                                else
                                {
                                    LogManager.Error($"无法解析路径类型: {jsonRoute.pathType}，路径: {jsonRoute.name}");
                                    continue;
                                }
                            }
                            else
                            {
                                LogManager.Error($"路径类型缺失，路径: {jsonRoute.name}");
                                continue;
                            }

                            if (!string.IsNullOrEmpty(jsonRoute.railMountMode) &&
                                Enum.TryParse<RailMountMode>(jsonRoute.railMountMode, out var railMountMode))
                            {
                                route.RailMountMode = railMountMode;
                            }

                            if (!string.IsNullOrEmpty(jsonRoute.railPathDefinitionMode) &&
                                Enum.TryParse<RailPathDefinitionMode>(jsonRoute.railPathDefinitionMode, out var railPathDefinitionMode))
                            {
                                route.RailPathDefinitionMode = railPathDefinitionMode;
                            }

                            route.RailNormalOffset = jsonRoute.railNormalOffset;

                            if (jsonRoute.railPreferredNormal != null)
                            {
                                route.RailPreferredNormal = new Point3D(
                                    jsonRoute.railPreferredNormal.x,
                                    jsonRoute.railPreferredNormal.y,
                                    jsonRoute.railPreferredNormal.z);
                            }

                            // 解析路径点
                            var points = new List<PathPoint>();
                            foreach (var jsonPoint in jsonRoute.points)
                            {
                                try
                                {
                                    if (jsonPoint == null) continue;

                                    // 验证路径点数据
                                    if (double.IsNaN(jsonPoint.x) || double.IsNaN(jsonPoint.y) || double.IsNaN(jsonPoint.z))
                                    {
                                        LogManager.Warning($"跳过无效路径点：坐标包含NaN值 (路径: {jsonRoute.name})");
                                        continue;
                                    }

                                    // 解析路径点类型
                                    if (!Enum.TryParse<PathPointType>(jsonPoint.type, out var pointType))
                                    {
                                        LogManager.Warning($"无法解析路径点类型: {jsonPoint.type}，使用默认值: WayPoint");
                                        pointType = PathPointType.WayPoint;
                                    }

                                    // 创建路径点
                                    var point = new PathPoint(
                                        new Point3D(jsonPoint.x, jsonPoint.y, jsonPoint.z),
                                        jsonPoint.name ?? $"{pointType}_{jsonPoint.index}",
                                        pointType
                                    )
                                    {
                                        Id = jsonPoint.id ?? Guid.NewGuid().ToString("N"),
                                        Index = jsonPoint.index,
                                        CreatedTime = ParseJsonDateTime(jsonPoint.created)
                                    };

                                    points.Add(point);
                                }
                                catch (Exception ex)
                                {
                                    LogManager.Warning($"[路径文件操作] 导入路径点失败: {ex.Message}");
                                    // 继续处理其他路径点
                                }
                            }

                            if (points.Count == 0)
                            {
                                LogManager.Warning($"跳过没有有效路径点的路径: {jsonRoute.name}");
                                continue;
                            }

                            // 按index排序并添加到路径
                            points = points.OrderBy(p => p.Index).ToList();
                            foreach (var point in points)
                            {
                                route.AddPoint(point);
                            }

                            // 验证路径有效性
                            if (route.IsValid())
                            {
                                routes.Add(route);
                                LogManager.Info($"[路径文件操作] 成功导入路径: {route.Name}，包含 {route.Points.Count} 个路径点");
                            }
                            else
                            {
                                LogManager.Warning($"跳过无效路径: {route.Name}");
                            }
                        }
                        catch (Exception ex)
                        {
                            LogManager.Error($"[路径文件操作] 导入路径失败: {jsonRoute.name ?? "Unknown"}，错误: {ex.Message}");
                            // 继续处理其他路径
                        }
                    }
                }
                else
                {
                    LogManager.Info("JSON文件中没有发现路径数据");
                }

                LogManager.Info($"JSON导入完成，共导入 {routes.Count} 条有效路径");

                return routes;
            }
            catch (FileNotFoundException)
            {
                LogManager.Error($"JSON导入失败：文件不存在: {filePath}");
                throw;
            }
            catch (InvalidOperationException ex) when (ex.Message.Contains("JSON"))
            {
                LogManager.Error($"JSON导入失败：文件格式不正确或JSON语法错误: {filePath}");
                throw new InvalidDataException("文件格式不正确或JSON语法错误", ex);
            }
            catch (Exception ex)
            {
                LogManager.Error($"JSON导入失败: {ex.Message}");
                throw new InvalidOperationException($"JSON导入失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 解析JSON中的日期时间字符串
        /// </summary>
        /// <param name="dateString">日期时间字符串</param>
        /// <returns>日期时间对象</returns>
        private DateTime ParseJsonDateTime(string dateString)
        {
            if (string.IsNullOrEmpty(dateString))
            {
                return DateTime.Now;
            }

            if (DateTime.TryParseExact(dateString, "yyyy-MM-ddTHH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var result))
            {
                return result;
            }

            // 尝试其他常见格式
            if (DateTime.TryParse(dateString, out result))
            {
                return result;
            }

            LogManager.Warning($"无法解析日期时间字符串: {dateString}，使用当前时间");
            return DateTime.Now;
        }

        /// <summary>
        /// 保存路径到Navisworks文件
        /// </summary>
        /// <param name="routes">路径集合</param>
        /// <param name="filePath">文件路径</param>
        /// <returns>是否成功</returns>
        public bool SaveToNavisworksFile(List<PathRoute> routes, string filePath)
        {
            try
            {
                // 创建临时属性来存储路径数据
                var document = Application.ActiveDocument ?? throw new InvalidOperationException("没有活动的Navisworks文档");

                // 简化实现：跳过路径数据序列化

                // 这里可以将路径数据保存为自定义属性
                // 由于Navisworks API的限制，这里是简化实现
                // 实际应用中可能需要使用COM API来添加自定义属性

                // 保存当前文档
                if (Path.GetExtension(filePath).ToLower() == ".nwd")
                {
                    // 创建NWD导出选项和发布属性
                    var exportOptions = new NwdExportOptions();
                    var publishProperties = new PublishProperties();
                    document.PublishFile(filePath, exportOptions, publishProperties);
                }
                else
                {
                    document.SaveFile(filePath);
                }

                return true;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"保存到Navisworks文件失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 从Navisworks文件加载路径
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns>路径集合</returns>
        public List<PathRoute> LoadFromNavisworksFile(string filePath)
        {
            var routes = new List<PathRoute>();

            try
            {
                // 这里应该从Navisworks文件的自定义属性中读取路径数据
                // 由于API限制，这里是简化实现
                // 实际应用中需要使用COM API来读取自定义属性

                return routes;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"从Navisworks文件加载失败: {ex.Message}");
                return routes;
            }
        }

        /// <summary>
        /// 导出DELMIA兼容格式
        /// </summary>
        /// <param name="routes">路径集合</param>
        /// <param name="filePath">文件路径</param>
        /// <param name="exportSettings">导出设置</param>
        /// <returns>是否成功</returns>
        public bool ExportDelmiaFormat(List<PathRoute> routes, string filePath, ExportSettings exportSettings = null)
        {
            try
            {
                // 确保导出目录存在
                var directory = Path.GetDirectoryName(filePath);
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }

                var xmlDoc = new XmlDocument();
                var declaration = xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", null);
                xmlDoc.AppendChild(declaration);

                // 创建DELMIA格式的根元素
                var rootElement = xmlDoc.CreateElement("DELMIA_PathPlanning", _delmiaNamespace);
                rootElement.SetAttribute("version", _delmiaVersion);
                rootElement.SetAttribute("units", exportSettings?.Units ?? "meters");
                xmlDoc.AppendChild(rootElement);

                // 添加任务信息
                var taskInfo = xmlDoc.CreateElement("TaskInfo", _delmiaNamespace);
                taskInfo.SetAttribute("name", exportSettings?.ProjectName ?? "物流路径规划");
                taskInfo.SetAttribute("description", exportSettings?.Description ?? "从Navisworks导出的路径规划任务");
                taskInfo.SetAttribute("created", DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss"));
                rootElement.AppendChild(taskInfo);

                // 添加路径集合
                var pathsElement = xmlDoc.CreateElement("Paths", _delmiaNamespace);
                rootElement.AppendChild(pathsElement);

                foreach (var route in routes.Where(r => r.IsValid()))
                {
                    var pathElement = CreateDelmiaPathElement(xmlDoc, route, exportSettings);
                    pathsElement.AppendChild(pathElement);
                }

                // 保存文件
                using (var writer = new XmlTextWriter(filePath, Encoding.UTF8))
                {
                    writer.Formatting = Formatting.Indented;
                    writer.Indentation = 2;
                    xmlDoc.WriteTo(writer);
                }

                return true;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"导出DELMIA格式失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 导出路径到DELMIA Apriso XML格式（符合TransportPathOrders Schema）
        /// </summary>
        /// <param name="routes">路径集合</param>
        /// <param name="filePath">文件路径</param>
        /// <param name="exportSettings">导出设置</param>
        /// <returns>是否成功</returns>
        public bool ExportToDelmiaAprisoXml(List<PathRoute> routes, string filePath, ExportSettings exportSettings = null)
        {
            if (routes == null || routes.Count == 0)
            {
                throw new ArgumentException("路径集合不能为空");
            }

            try
            {
                LogManager.Info($"[路径文件操作] 开始导出 {routes.Count} 条路径到DELMIA Apriso XML文件: {filePath}");

                // 确保导出目录存在
                var directory = Path.GetDirectoryName(filePath);
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }

                var xmlDoc = new XmlDocument();
                var declaration = xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", null);
                xmlDoc.AppendChild(declaration);

                // DELMIA Apriso命名空间
                const string ns = "http://www.dassaultsystemes.com/delmia/apriso";
                const string nsPrefix = "apr";

                // 创建根元素 TransportPathOrders
                var rootElement = xmlDoc.CreateElement(nsPrefix, "TransportPathOrders", ns);
                xmlDoc.AppendChild(rootElement);

                // 为每个路径创建PathOrder
                foreach (var route in routes.Where(r => r.IsValid()))
                {
                    var pathOrderElement = CreateDelmiaAprisoPathOrderElement(xmlDoc, route, exportSettings, ns, nsPrefix);
                    rootElement.AppendChild(pathOrderElement);
                }

                // 保存文件
                using (var writer = new XmlTextWriter(filePath, Encoding.UTF8))
                {
                    writer.Formatting = Formatting.Indented;
                    writer.Indentation = 2;
                    xmlDoc.WriteTo(writer);
                }

                LogManager.Info($"[路径文件操作] 成功导出 {routes.Count} 条路径到DELMIA Apriso XML文件: {filePath}");
                return true;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[路径文件操作] 导出DELMIA Apriso XML文件失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 创建DELMIA Apriso格式的PathOrder元素
        /// </summary>
        private XmlElement CreateDelmiaAprisoPathOrderElement(XmlDocument xmlDoc, PathRoute route, ExportSettings settings, string ns, string nsPrefix)
        {
            var pathOrderElement = xmlDoc.CreateElement(nsPrefix, "PathOrder", ns);

            // 基础信息
            var orderIdElement = xmlDoc.CreateElement(nsPrefix, "OrderId", ns);
            orderIdElement.InnerText = route.Id ?? Guid.NewGuid().ToString();
            pathOrderElement.AppendChild(orderIdElement);

            var orderNameElement = xmlDoc.CreateElement(nsPrefix, "OrderName", ns);
            orderNameElement.InnerText = route.Name ?? "未命名路径";
            pathOrderElement.AppendChild(orderNameElement);

            var descriptionElement = xmlDoc.CreateElement(nsPrefix, "Description", ns);
            descriptionElement.InnerText = route.Description ?? $"NavisworksTransport生成的路径: {route.Name}";
            pathOrderElement.AppendChild(descriptionElement);

            var pathTypeElement = xmlDoc.CreateElement(nsPrefix, "PathType", ns);
            pathTypeElement.InnerText = MapToDelmiaPathType(route.PathType);
            pathOrderElement.AppendChild(pathTypeElement);

            var totalLengthElement = xmlDoc.CreateElement(nsPrefix, "TotalLength", ns);
            totalLengthElement.InnerText = route.TotalLength.ToString("F3", CultureInfo.InvariantCulture);
            pathOrderElement.AppendChild(totalLengthElement);

            var timestampElement = xmlDoc.CreateElement(nsPrefix, "Timestamp", ns);
            timestampElement.InnerText = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
            pathOrderElement.AppendChild(timestampElement);

            var generatorElement = xmlDoc.CreateElement(nsPrefix, "Generator", ns);
            generatorElement.InnerText = "NavisworksTransport";
            pathOrderElement.AppendChild(generatorElement);

            var versionElement = xmlDoc.CreateElement(nsPrefix, "Version", ns);
            versionElement.InnerText = "1.0";
            pathOrderElement.AppendChild(versionElement);

            // 创建Nodes
            var nodesElement = xmlDoc.CreateElement(nsPrefix, "Nodes", ns);
            pathOrderElement.AppendChild(nodesElement);

            var sortedPoints = route.GetSortedPoints();
            for (int i = 0; i < sortedPoints.Count; i++)
            {
                var point = sortedPoints[i];
                var nodeElement = xmlDoc.CreateElement(nsPrefix, "Node", ns);

                // NodeId
                var nodeIdElement = xmlDoc.CreateElement(nsPrefix, "NodeId", ns);
                nodeIdElement.InnerText = point.Id ?? $"node_{i}";
                nodeElement.AppendChild(nodeIdElement);

                // SequenceId
                var sequenceIdElement = xmlDoc.CreateElement(nsPrefix, "SequenceId", ns);
                sequenceIdElement.InnerText = i.ToString();
                nodeElement.AppendChild(sequenceIdElement);

                // NodeName
                var nodeNameElement = xmlDoc.CreateElement(nsPrefix, "NodeName", ns);
                nodeNameElement.InnerText = point.Name ?? $"点{i}";
                nodeElement.AppendChild(nodeNameElement);

                // NodeType (映射到DELMIA枚举，支持吊装路径特殊类型)
                var nodeTypeElement = xmlDoc.CreateElement(nsPrefix, "NodeType", ns);
                string nodeType = MapToDelmiaNodeType(point.Type, route.PathType, i, sortedPoints.Count);
                nodeTypeElement.InnerText = nodeType;
                nodeElement.AppendChild(nodeTypeElement);

                // 吊装路径特殊属性：LiftHeight (仅对LiftPoint和HoverPoint)
                if ((nodeType == "LiftPoint" || nodeType == "HoverPoint") && route.LiftHeight > 0)
                {
                    var liftHeightElement = xmlDoc.CreateElement(nsPrefix, "LiftHeight", ns);
                    liftHeightElement.InnerText = route.LiftHeight.ToString("F3", CultureInfo.InvariantCulture);
                    nodeElement.AppendChild(liftHeightElement);
                }

                // Position
                var positionElement = xmlDoc.CreateElement(nsPrefix, "Position", ns);
                var xElement = xmlDoc.CreateElement(nsPrefix, "X", ns);
                xElement.InnerText = point.Position.X.ToString("F3", CultureInfo.InvariantCulture);
                positionElement.AppendChild(xElement);
                var yElement = xmlDoc.CreateElement(nsPrefix, "Y", ns);
                yElement.InnerText = point.Position.Y.ToString("F3", CultureInfo.InvariantCulture);
                positionElement.AppendChild(yElement);
                var zElement = xmlDoc.CreateElement(nsPrefix, "Z", ns);
                zElement.InnerText = point.Position.Z.ToString("F3", CultureInfo.InvariantCulture);
                positionElement.AppendChild(zElement);
                nodeElement.AppendChild(positionElement);

                // Released
                var releasedElement = xmlDoc.CreateElement(nsPrefix, "Released", ns);
                releasedElement.InnerText = "true";
                nodeElement.AppendChild(releasedElement);

                nodesElement.AppendChild(nodeElement);
            }

            // 创建Edges
            var edgesElement = xmlDoc.CreateElement(nsPrefix, "Edges", ns);
            pathOrderElement.AppendChild(edgesElement);

            if (route.Edges != null && route.Edges.Count > 0)
            {
                for (int i = 0; i < route.Edges.Count && i < sortedPoints.Count - 1; i++)
                {
                    var edge = route.Edges[i];
                    var startNode = sortedPoints[i];
                    var endNode = sortedPoints[i + 1];

                    var edgeElement = xmlDoc.CreateElement(nsPrefix, "Edge", ns);

                    // EdgeId
                    var edgeIdElement = xmlDoc.CreateElement(nsPrefix, "EdgeId", ns);
                    edgeIdElement.InnerText = $"edge_{i}";
                    edgeElement.AppendChild(edgeIdElement);

                    // EdgeType (支持吊装路径特殊类型)
                    var edgeTypeElement = xmlDoc.CreateElement(nsPrefix, "EdgeType", ns);
                    string edgeType = MapToDelmiaEdgeType(edge.SegmentType, route.PathType);
                    edgeTypeElement.InnerText = edgeType;
                    edgeElement.AppendChild(edgeTypeElement);

                    // SequenceId
                    var edgeSeqIdElement = xmlDoc.CreateElement(nsPrefix, "SequenceId", ns);
                    edgeSeqIdElement.InnerText = i.ToString();
                    edgeElement.AppendChild(edgeSeqIdElement);

                    // StartNodeId
                    var startNodeIdElement = xmlDoc.CreateElement(nsPrefix, "StartNodeId", ns);
                    startNodeIdElement.InnerText = startNode.Id ?? $"node_{i}";
                    edgeElement.AppendChild(startNodeIdElement);

                    // EndNodeId
                    var endNodeIdElement = xmlDoc.CreateElement(nsPrefix, "EndNodeId", ns);
                    endNodeIdElement.InnerText = endNode.Id ?? $"node_{i + 1}";
                    edgeElement.AppendChild(endNodeIdElement);

                    // PhysicalLength
                    var physicalLengthElement = xmlDoc.CreateElement(nsPrefix, "PhysicalLength", ns);
                    physicalLengthElement.InnerText = edge.PhysicalLength.ToString("F3", CultureInfo.InvariantCulture);
                    edgeElement.AppendChild(physicalLengthElement);

                    // Trajectory (如果是弧线)
                    if (edge.SegmentType == PathSegmentType.Arc && edge.Trajectory != null)
                    {
                        var trajectoryElement = xmlDoc.CreateElement(nsPrefix, "Trajectory", ns);

                        // StartTangent
                        var startTangentElement = xmlDoc.CreateElement(nsPrefix, "StartTangent", ns);
                        var stXElement = xmlDoc.CreateElement(nsPrefix, "X", ns);
                        stXElement.InnerText = edge.Trajectory.Ts.X.ToString("F3", CultureInfo.InvariantCulture);
                        startTangentElement.AppendChild(stXElement);
                        var stYElement = xmlDoc.CreateElement(nsPrefix, "Y", ns);
                        stYElement.InnerText = edge.Trajectory.Ts.Y.ToString("F3", CultureInfo.InvariantCulture);
                        startTangentElement.AppendChild(stYElement);
                        var stZElement = xmlDoc.CreateElement(nsPrefix, "Z", ns);
                        stZElement.InnerText = edge.Trajectory.Ts.Z.ToString("F3", CultureInfo.InvariantCulture);
                        startTangentElement.AppendChild(stZElement);
                        trajectoryElement.AppendChild(startTangentElement);

                        // EndTangent
                        var endTangentElement = xmlDoc.CreateElement(nsPrefix, "EndTangent", ns);
                        var etXElement = xmlDoc.CreateElement(nsPrefix, "X", ns);
                        etXElement.InnerText = edge.Trajectory.Te.X.ToString("F3", CultureInfo.InvariantCulture);
                        endTangentElement.AppendChild(etXElement);
                        var etYElement = xmlDoc.CreateElement(nsPrefix, "Y", ns);
                        etYElement.InnerText = edge.Trajectory.Te.Y.ToString("F3", CultureInfo.InvariantCulture);
                        endTangentElement.AppendChild(etYElement);
                        var etZElement = xmlDoc.CreateElement(nsPrefix, "Z", ns);
                        etZElement.InnerText = edge.Trajectory.Te.Z.ToString("F3", CultureInfo.InvariantCulture);
                        endTangentElement.AppendChild(etZElement);
                        trajectoryElement.AppendChild(endTangentElement);

                        // ArcCenter
                        var arcCenterElement = xmlDoc.CreateElement(nsPrefix, "ArcCenter", ns);
                        var acXElement = xmlDoc.CreateElement(nsPrefix, "X", ns);
                        acXElement.InnerText = edge.Trajectory.ArcCenter.X.ToString("F3", CultureInfo.InvariantCulture);
                        arcCenterElement.AppendChild(acXElement);
                        var acYElement = xmlDoc.CreateElement(nsPrefix, "Y", ns);
                        acYElement.InnerText = edge.Trajectory.ArcCenter.Y.ToString("F3", CultureInfo.InvariantCulture);
                        arcCenterElement.AppendChild(acYElement);
                        var acZElement = xmlDoc.CreateElement(nsPrefix, "Z", ns);
                        acZElement.InnerText = edge.Trajectory.ArcCenter.Z.ToString("F3", CultureInfo.InvariantCulture);
                        arcCenterElement.AppendChild(acZElement);
                        trajectoryElement.AppendChild(arcCenterElement);

                        // Radius
                        var radiusElement = xmlDoc.CreateElement(nsPrefix, "Radius", ns);
                        radiusElement.InnerText = edge.Trajectory.ActualRadius.ToString("F3", CultureInfo.InvariantCulture);
                        trajectoryElement.AppendChild(radiusElement);

                        // DeflectionAngle
                        var deflectionAngleElement = xmlDoc.CreateElement(nsPrefix, "DeflectionAngle", ns);
                        deflectionAngleElement.InnerText = edge.Trajectory.DeflectionAngle.ToString("F3", CultureInfo.InvariantCulture);
                        trajectoryElement.AppendChild(deflectionAngleElement);

                        edgeElement.AppendChild(trajectoryElement);
                    }

                    edgesElement.AppendChild(edgeElement);
                }
            }

            // ObjectLimits (使用 -1 表示无限制)
            var objectLimitsElement = xmlDoc.CreateElement(nsPrefix, "ObjectLimits", ns);
            
            var maxLengthElement = xmlDoc.CreateElement(nsPrefix, "MaxLength", ns);
            maxLengthElement.InnerText = (route.MaxObjectLength > 0 ? route.MaxObjectLength : -1).ToString("F3", CultureInfo.InvariantCulture);
            objectLimitsElement.AppendChild(maxLengthElement);
            
            var maxWidthElement = xmlDoc.CreateElement(nsPrefix, "MaxWidth", ns);
            maxWidthElement.InnerText = (route.MaxObjectWidth > 0 ? route.MaxObjectWidth : -1).ToString("F3", CultureInfo.InvariantCulture);
            objectLimitsElement.AppendChild(maxWidthElement);
            
            var maxHeightElement = xmlDoc.CreateElement(nsPrefix, "MaxHeight", ns);
            maxHeightElement.InnerText = (route.MaxObjectHeight > 0 ? route.MaxObjectHeight : -1).ToString("F3", CultureInfo.InvariantCulture);
            objectLimitsElement.AppendChild(maxHeightElement);
            
            var safetyMarginElement = xmlDoc.CreateElement(nsPrefix, "SafetyMargin", ns);
            safetyMarginElement.InnerText = (route.SafetyMargin >= 0 ? route.SafetyMargin : 0.5).ToString("F3", CultureInfo.InvariantCulture);
            objectLimitsElement.AppendChild(safetyMarginElement);
            
            // MaxWeight (新增，默认 -1 表示无限制)
            var maxWeightElement = xmlDoc.CreateElement(nsPrefix, "MaxWeight", ns);
            maxWeightElement.InnerText = "-1";
            objectLimitsElement.AppendChild(maxWeightElement);
            
            pathOrderElement.AppendChild(objectLimitsElement);

            // CoordinateSystem
            var coordinateSystemElement = xmlDoc.CreateElement(nsPrefix, "CoordinateSystem", ns);
            coordinateSystemElement.InnerText = settings?.CoordinateSystem ?? "Global";
            pathOrderElement.AppendChild(coordinateSystemElement);

            return pathOrderElement;
        }

        /// <summary>
        /// 将PathPointType映射到DELMIA NodeType枚举
        /// 支持吊装路径特殊节点类型：LiftPoint, DescendPoint, HoverPoint
        /// </summary>
        private string MapToDelmiaNodeType(PathPointType type, PathType pathType = PathType.Ground, int pointIndex = 0, int totalPoints = 0)
        {
            // 基础类型映射
            switch (type)
            {
                case PathPointType.StartPoint:
                    return "StartPoint";
                case PathPointType.EndPoint:
                    return "EndPoint";
                case PathPointType.WayPoint:
                default:
                    // 对于吊装路径，根据点位置判断特殊类型
                    if (pathType == PathType.Hoisting && totalPoints > 2)
                    {
                        // 吊装路径的第二点通常是提升点
                        if (pointIndex == 1)
                            return "LiftPoint";
                        // 吊装路径的倒数第二点通常是下降点
                        if (pointIndex == totalPoints - 2)
                            return "DescendPoint";
                        // 中间空中点
                        if (pointIndex > 1 && pointIndex < totalPoints - 2)
                            return "HoverPoint";
                    }
                    return "WayPoint";
            }
        }

        /// <summary>
        /// 将PathType映射到DELMIA PathTypeEnum
        /// </summary>
        private string MapToDelmiaPathType(PathType pathType)
        {
            switch (pathType)
            {
                case PathType.Ground:
                    return "Ground";
                case PathType.Rail:
                case PathType.Hoisting:
                    return "Aerial";
                default:
                    return "Mixed";
            }
        }

        /// <summary>
        /// 将PathSegmentType映射到DELMIA EdgeTypeEnum
        /// 支持吊装路径特殊边类型：vertical, suspension, hoisting
        /// </summary>
        private string MapToDelmiaEdgeType(PathSegmentType segmentType, PathType pathType = PathType.Ground)
        {
            switch (segmentType)
            {
                case PathSegmentType.Arc:
                    return "arc";
                case PathSegmentType.Straight:
                default:
                    // 对于吊装路径，根据上下文判断是否为垂直运动
                    if (pathType == PathType.Hoisting)
                        return "hoisting";
                    if (pathType == PathType.Rail)
                        return "suspension";
                    return "straight";
            }
        }

        /// <summary>
        /// 获取默认导出路径
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="format">格式</param>
        /// <returns>完整路径</returns>
        public string GetDefaultExportPath(string fileName, ExportFormat format)
        {
            var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            var exportPath = Path.Combine(documentsPath, DEFAULT_EXPORT_FOLDER);

            if (!Directory.Exists(exportPath))
            {
                Directory.CreateDirectory(exportPath);
            }

            string extension;
            switch (format)
            {
                case ExportFormat.Json:
                    extension = JSON_FILE_EXTENSION;
                    break;
                case ExportFormat.Csv:
                    extension = CSV_FILE_EXTENSION;
                    break;
                default:
                    extension = DEFAULT_FILE_EXTENSION;
                    break;
            }

            return Path.Combine(exportPath, fileName + extension);
        }

        /// <summary>
        /// 验证导出文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="format">格式</param>
        /// <returns>验证结果</returns>
        public ValidationResult ValidateExportFile(string filePath, ExportFormat format)
        {
            var result = new ValidationResult();

            try
            {
                if (!File.Exists(filePath))
                {
                    result.IsValid = false;
                    result.Errors.Add("文件不存在");
                    return result;
                }

                if (format == ExportFormat.Xml)
                {
                    // 验证XML格式
                    var xmlDoc = new XmlDocument();
                    xmlDoc.Load(filePath);

                    if (xmlDoc.DocumentElement?.Name != "PathPlanningData" &&
                        xmlDoc.DocumentElement?.Name != "DELMIA_PathPlanning")
                    {
                        result.Warnings.Add("XML根元素格式可能不正确");
                    }
                }
                else if (format == ExportFormat.Json)
                {
                    // 验证JSON格式
                    try
                    {
                        var jsonContent = File.ReadAllText(filePath, Encoding.UTF8);
                        var serializer = new JavaScriptSerializer();
                        var parsed = serializer.DeserializeObject(jsonContent);
                        
                        if (parsed == null)
                        {
                            result.Errors.Add("JSON文件格式无效");
                        }
                        else if (!jsonContent.Contains("PathPlanningData"))
                        {
                            result.Warnings.Add("JSON文件可能不包含路径规划数据结构");
                        }
                    }
                    catch (Exception jsonEx)
                    {
                        result.Errors.Add($"JSON格式验证失败: {jsonEx.Message}");
                    }
                }
                else if (format == ExportFormat.Csv)
                {
                    // 验证CSV格式
                    try
                    {
                        var lines = File.ReadAllLines(filePath, Encoding.UTF8);
                        if (lines.Length == 0)
                        {
                            result.Errors.Add("CSV文件为空");
                        }
                        else if (!lines[0].Contains("路径名称") || !lines[0].Contains("X坐标"))
                        {
                            result.Warnings.Add("CSV文件头格式可能不正确");
                        }
                        else if (lines.Length < 2)
                        {
                            result.Warnings.Add("CSV文件只包含表头，没有数据行");
                        }
                    }
                    catch (Exception csvEx)
                    {
                        result.Errors.Add($"CSV格式验证失败: {csvEx.Message}");
                    }
                }

                result.IsValid = true;
            }
            catch (Exception ex)
            {
                result.IsValid = false;
                result.Errors.Add($"文件验证失败: {ex.Message}");
            }

            return result;
        }

        #region 私有辅助方法

        /// <summary>
        /// 格式化JSON字符串（简单的美化）
        /// </summary>
        private string FormatJsonString(string jsonString)
        {
            try
            {
                var indent = 0;
                var formatted = new StringBuilder();
                var inString = false;
                var escape = false;

                foreach (char c in jsonString)
                {
                    if (!escape && c == '"')
                        inString = !inString;

                    if (!inString)
                    {
                        switch (c)
                        {
                            case '{':
                            case '[':
                                formatted.Append(c);
                                formatted.AppendLine();
                                formatted.Append(new string(' ', ++indent * 2));
                                break;
                            case '}':
                            case ']':
                                formatted.AppendLine();
                                formatted.Append(new string(' ', --indent * 2));
                                formatted.Append(c);
                                break;
                            case ',':
                                formatted.Append(c);
                                formatted.AppendLine();
                                formatted.Append(new string(' ', indent * 2));
                                break;
                            case ':':
                                formatted.Append(c);
                                formatted.Append(' ');
                                break;
                            default:
                                formatted.Append(c);
                                break;
                        }
                    }
                    else
                    {
                        formatted.Append(c);
                    }

                    escape = !escape && c == '\\';
                }

                return formatted.ToString();
            }
            catch
            {
                // 如果格式化失败，返回原始字符串
                return jsonString;
            }
        }

        /// <summary>
        /// 转义CSV值，处理逗号、引号和换行符
        /// </summary>
        private string EscapeCsvValue(string value)
        {
            if (string.IsNullOrEmpty(value))
                return "\"\"";

            // 如果包含逗号、引号或换行符，需要用引号包围并转义内部引号
            if (value.Contains(",") || value.Contains("\"") || value.Contains("\n") || value.Contains("\r"))
            {
                value = value.Replace("\"", "\"\""); // 转义引号
                return $"\"{value}\"";
            }

            return value;
        }

        /// <summary>
        /// 创建项目信息元素
        /// </summary>
        private XmlElement CreateProjectInfoElement(XmlDocument xmlDoc, ExportSettings settings)
        {
            var projectInfo = xmlDoc.CreateElement("ProjectInfo", _delmiaNamespace);
            projectInfo.SetAttribute("name", settings?.ProjectName ?? "NavisworksTransport路径规划");
            projectInfo.SetAttribute("description", settings?.Description ?? "物流路径规划数据");
            projectInfo.SetAttribute("units", settings?.Units ?? "meters");
            projectInfo.SetAttribute("coordinateSystem", settings?.CoordinateSystem ?? "Global");

            return projectInfo;
        }

        /// <summary>
        /// 创建路径元素
        /// </summary>
        private XmlElement CreateRouteElement(XmlDocument xmlDoc, PathRoute route, ExportSettings settings)
        {
            var routeElement = xmlDoc.CreateElement("Route", _delmiaNamespace);
            routeElement.SetAttribute("id", route.Id);
            routeElement.SetAttribute("name", route.Name);
            routeElement.SetAttribute("description", route.Description ?? "");
            routeElement.SetAttribute("pathType", route.PathType.ToString());
            routeElement.SetAttribute("railMountMode", route.RailMountMode.ToString());
            routeElement.SetAttribute("railPathDefinitionMode", route.RailPathDefinitionMode.ToString());
            routeElement.SetAttribute("railNormalOffset", route.RailNormalOffset.ToString("F3"));
            if (route.RailPreferredNormal != null)
            {
                routeElement.SetAttribute("railPreferredNormalX", route.RailPreferredNormal.X.ToString("F3"));
                routeElement.SetAttribute("railPreferredNormalY", route.RailPreferredNormal.Y.ToString("F3"));
                routeElement.SetAttribute("railPreferredNormalZ", route.RailPreferredNormal.Z.ToString("F3"));
            }
            routeElement.SetAttribute("totalLength", route.TotalLength.ToString("F3"));
            routeElement.SetAttribute("maxObjectLength", route.MaxObjectLength.ToString("F3"));
            routeElement.SetAttribute("maxObjectWidth", route.MaxObjectWidth.ToString("F3"));
            routeElement.SetAttribute("maxObjectHeight", route.MaxObjectHeight.ToString("F3"));
            routeElement.SetAttribute("safetyMargin", route.SafetyMargin.ToString("F3"));
            routeElement.SetAttribute("gridSize", route.GridSize.ToString("F3"));
            routeElement.SetAttribute("liftHeight", route.LiftHeight.ToString("F3"));
            routeElement.SetAttribute("created", route.CreatedTime.ToString("yyyy-MM-ddTHH:mm:ss"));

            // 添加路径点
            var pointsElement = xmlDoc.CreateElement("Points", _delmiaNamespace);
            routeElement.AppendChild(pointsElement);

            var sortedPoints = route.GetSortedPoints();
            foreach (var point in sortedPoints)
            {
                var pointElement = xmlDoc.CreateElement("Point", _delmiaNamespace);
                pointElement.SetAttribute("id", point.Id);
                pointElement.SetAttribute("name", point.Name);
                pointElement.SetAttribute("type", point.Type.ToString());
                pointElement.SetAttribute("index", point.Index.ToString());
                pointElement.SetAttribute("x", point.Position.X.ToString("F3"));
                pointElement.SetAttribute("y", point.Position.Y.ToString("F3"));
                pointElement.SetAttribute("z", point.Position.Z.ToString("F3"));
                pointElement.SetAttribute("created", point.CreatedTime.ToString("yyyy-MM-ddTHH:mm:ss"));

                pointsElement.AppendChild(pointElement);
            }

            // 添加路径边
            if (route.Edges != null && route.Edges.Count > 0)
            {
                var edgesElement = xmlDoc.CreateElement("Edges", _delmiaNamespace);
                routeElement.AppendChild(edgesElement);

                foreach (var edge in route.Edges)
                {
                    var edgeElement = xmlDoc.CreateElement("Edge", _delmiaNamespace);
                    edgeElement.SetAttribute("type", edge.SegmentType.ToString().ToLower());
                    edgeElement.SetAttribute("physicalLength", edge.PhysicalLength.ToString("F3"));

                    // 圆弧轨迹数据
                    if (edge.SegmentType == PathSegmentType.Arc && edge.Trajectory != null)
                    {
                        var trajElement = xmlDoc.CreateElement("Trajectory", _delmiaNamespace);

                        // 进入切点
                        var tsElement = xmlDoc.CreateElement("Ts", _delmiaNamespace);
                        tsElement.SetAttribute("x", edge.Trajectory.Ts.X.ToString("F3"));
                        tsElement.SetAttribute("y", edge.Trajectory.Ts.Y.ToString("F3"));
                        tsElement.SetAttribute("z", edge.Trajectory.Ts.Z.ToString("F3"));
                        trajElement.AppendChild(tsElement);

                        // 退出切点
                        var teElement = xmlDoc.CreateElement("Te", _delmiaNamespace);
                        teElement.SetAttribute("x", edge.Trajectory.Te.X.ToString("F3"));
                        teElement.SetAttribute("y", edge.Trajectory.Te.Y.ToString("F3"));
                        teElement.SetAttribute("z", edge.Trajectory.Te.Z.ToString("F3"));
                        trajElement.AppendChild(teElement);

                        // 圆心
                        var centerElement = xmlDoc.CreateElement("ArcCenter", _delmiaNamespace);
                        centerElement.SetAttribute("x", edge.Trajectory.ArcCenter.X.ToString("F3"));
                        centerElement.SetAttribute("y", edge.Trajectory.ArcCenter.Y.ToString("F3"));
                        centerElement.SetAttribute("z", edge.Trajectory.ArcCenter.Z.ToString("F3"));
                        trajElement.AppendChild(centerElement);

                        // 请求半径
                        var requestedRadiusElement = xmlDoc.CreateElement("RequestedRadius", _delmiaNamespace);
                        requestedRadiusElement.InnerText = edge.Trajectory.RequestedRadius.ToString("F3");
                        trajElement.AppendChild(requestedRadiusElement);

                        // 实际半径
                        var radiusElement = xmlDoc.CreateElement("ActualRadius", _delmiaNamespace);
                        radiusElement.InnerText = edge.Trajectory.ActualRadius.ToString("F3");
                        trajElement.AppendChild(radiusElement);

                        // 偏转角
                        var angleElement = xmlDoc.CreateElement("DeflectionAngle", _delmiaNamespace);
                        angleElement.InnerText = edge.Trajectory.DeflectionAngle.ToString("F3");
                        trajElement.AppendChild(angleElement);

                        // 圆弧长度
                        var arcLengthElement = xmlDoc.CreateElement("ArcLength", _delmiaNamespace);
                        arcLengthElement.InnerText = edge.Trajectory.ArcLength.ToString("F3");
                        trajElement.AppendChild(arcLengthElement);

                        edgeElement.AppendChild(trajElement);
                    }

                    edgesElement.AppendChild(edgeElement);
                }
            }

            return routeElement;
        }

        /// <summary>
        /// 解析路径元素
        /// </summary>
        private PathRoute ParseRouteElement(XmlNode routeNode)
        {
            try
            {
                // 🔥 路径类型是必需字段
                var pathTypeStr = routeNode.Attributes?["pathType"]?.Value;
                if (string.IsNullOrEmpty(pathTypeStr))
                {
                    LogManager.Error("XML导入失败：路径类型(pathType)属性缺失");
                    return null;
                }

                if (!Enum.TryParse<PathType>(pathTypeStr, out var pathType))
                {
                    LogManager.Error($"XML导入失败：无法解析路径类型 '{pathTypeStr}'");
                    return null;
                }

                var route = new PathRoute
                {
                    Id = routeNode.Attributes?["id"]?.Value ?? Guid.NewGuid().ToString(),
                    Name = routeNode.Attributes?["name"]?.Value ?? "导入路径",
                    Description = routeNode.Attributes?["description"]?.Value ?? "",
                    PathType = pathType,
                    MaxObjectLength = double.TryParse(routeNode.Attributes?["maxObjectLength"]?.Value, out double maxLength) ? maxLength : 0,
                    MaxObjectWidth = double.TryParse(routeNode.Attributes?["maxObjectWidth"]?.Value, out double maxWidth) ? maxWidth : 0,
                    MaxObjectHeight = double.TryParse(routeNode.Attributes?["maxObjectHeight"]?.Value, out double maxHeight) ? maxHeight : 0,
                    SafetyMargin = double.TryParse(routeNode.Attributes?["safetyMargin"]?.Value, out double safetyMargin) ? safetyMargin : 0,
                    GridSize = double.TryParse(routeNode.Attributes?["gridSize"]?.Value, out double gridSize) ? gridSize : 0,
                    LiftHeight = double.TryParse(routeNode.Attributes?["liftHeight"]?.Value, out double liftHeight) ? liftHeight : 0
                };

                if (Enum.TryParse<RailMountMode>(routeNode.Attributes?["railMountMode"]?.Value, out var railMountMode))
                {
                    route.RailMountMode = railMountMode;
                }

                if (Enum.TryParse<RailPathDefinitionMode>(routeNode.Attributes?["railPathDefinitionMode"]?.Value, out var railPathDefinitionMode))
                {
                    route.RailPathDefinitionMode = railPathDefinitionMode;
                }

                if (double.TryParse(routeNode.Attributes?["railNormalOffset"]?.Value, out var railNormalOffset))
                {
                    route.RailNormalOffset = railNormalOffset;
                }

                if (double.TryParse(routeNode.Attributes?["railPreferredNormalX"]?.Value, out var railPreferredNormalX) &&
                    double.TryParse(routeNode.Attributes?["railPreferredNormalY"]?.Value, out var railPreferredNormalY) &&
                    double.TryParse(routeNode.Attributes?["railPreferredNormalZ"]?.Value, out var railPreferredNormalZ))
                {
                    route.RailPreferredNormal = new Point3D(
                        railPreferredNormalX,
                        railPreferredNormalY,
                        railPreferredNormalZ);
                }

                // 解析创建时间
                if (DateTime.TryParse(routeNode.Attributes?["created"]?.Value, out DateTime createdTime))
                {
                    route.CreatedTime = createdTime;
                }

                // 解析路径点
                var pointsNode = routeNode.SelectSingleNode("*[local-name()='Points']");
                if (pointsNode != null)
                {
                    foreach (XmlNode pointNode in pointsNode.ChildNodes)
                    {
                        if (pointNode.NodeType == XmlNodeType.Element)
                        {
                            var point = ParsePointElement(pointNode);
                            if (point != null)
                            {
                                route.Points.Add(point);
                            }
                        }
                    }
                    // 仅在内存中重建几何/索引，不触发数据库保存
                    route.RecalculateRoute("XML导入");
                }

                return route;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"解析路径元素失败: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 解析路径点元素
        /// </summary>
        private PathPoint ParsePointElement(XmlNode pointNode)
        {
            try
            {
                var point = new PathPoint
                {
                    Id = pointNode.Attributes?["id"]?.Value ?? Guid.NewGuid().ToString(),
                    Name = pointNode.Attributes?["name"]?.Value ?? ""
                };

                // 解析位置
                if (double.TryParse(pointNode.Attributes?["x"]?.Value, out double x) &&
                    double.TryParse(pointNode.Attributes?["y"]?.Value, out double y) &&
                    double.TryParse(pointNode.Attributes?["z"]?.Value, out double z))
                {
                    point.Position = new Point3D(x, y, z);
                }

                // 解析索引
                if (int.TryParse(pointNode.Attributes?["index"]?.Value, out int index))
                {
                    point.Index = index;
                }

                // 解析类型
                if (Enum.TryParse<PathPointType>(pointNode.Attributes?["type"]?.Value, out PathPointType type))
                {
                    point.Type = type;
                }

                // 解析创建时间
                if (DateTime.TryParse(pointNode.Attributes?["created"]?.Value, out DateTime createdTime))
                {
                    point.CreatedTime = createdTime;
                }

                return point;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"解析路径点元素失败: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 创建DELMIA路径元素
        /// </summary>
        private XmlElement CreateDelmiaPathElement(XmlDocument xmlDoc, PathRoute route, ExportSettings settings)
        {
            var pathElement = xmlDoc.CreateElement("Path", _delmiaNamespace);
            pathElement.SetAttribute("id", route.Id);
            pathElement.SetAttribute("name", route.Name);
            pathElement.SetAttribute("type", "Transportation");
            pathElement.SetAttribute("length", route.TotalLength.ToString("F3"));

            // 添加物体限制元素
            var objectConstraints = xmlDoc.CreateElement("ObjectConstraints", _delmiaNamespace);
            objectConstraints.SetAttribute("maxLength", route.MaxObjectLength.ToString("F3"));
            objectConstraints.SetAttribute("maxWidth", route.MaxObjectWidth.ToString("F3"));
            objectConstraints.SetAttribute("maxHeight", route.MaxObjectHeight.ToString("F3"));
            objectConstraints.SetAttribute("safetyMargin", route.SafetyMargin.ToString("F3"));
            objectConstraints.SetAttribute("gridSize", route.GridSize.ToString("F3"));
            pathElement.AppendChild(objectConstraints);

            // 添加路径段
            var segmentsElement = xmlDoc.CreateElement("Segments", _delmiaNamespace);
            pathElement.AppendChild(segmentsElement);

            var sortedPoints = route.GetSortedPoints();
            for (int i = 0; i < sortedPoints.Count - 1; i++)
            {
                var segmentElement = xmlDoc.CreateElement("Segment", _delmiaNamespace);
                segmentElement.SetAttribute("index", i.ToString());

                // 起点
                var startElement = xmlDoc.CreateElement("Start", _delmiaNamespace);
                AddDelmiaPointData(xmlDoc, startElement, sortedPoints[i]);
                segmentElement.AppendChild(startElement);

                // 终点
                var endElement = xmlDoc.CreateElement("End", _delmiaNamespace);
                AddDelmiaPointData(xmlDoc, endElement, sortedPoints[i + 1]);
                segmentElement.AppendChild(endElement);

                segmentsElement.AppendChild(segmentElement);
            }

            return pathElement;
        }

        /// <summary>
        /// 添加DELMIA点数据
        /// </summary>
        private void AddDelmiaPointData(XmlDocument xmlDoc, XmlElement element, PathPoint point)
        {
            element.SetAttribute("x", point.Position.X.ToString("F3"));
            element.SetAttribute("y", point.Position.Y.ToString("F3"));
            element.SetAttribute("z", point.Position.Z.ToString("F3"));
            element.SetAttribute("name", point.Name);
            element.SetAttribute("type", point.Type.ToString());
        }

        #endregion
    }

    /// <summary>
    /// 导出格式枚举
    /// </summary>
    public enum ExportFormat
    {
        Xml,
        Json,
        Csv,
        Delmia,
        Navisworks,
        DelmiaApriso
    }

    /// <summary>
    /// 导出设置
    /// </summary>
    public class ExportSettings
    {
        /// <summary>
        /// 项目名称
        /// </summary>
        public string ProjectName { get; set; } = "NavisworksTransport路径规划";

        /// <summary>
        /// 项目描述
        /// </summary>
        public string Description { get; set; } = "物流路径规划数据";

        /// <summary>
        /// 单位
        /// </summary>
        public string Units { get; set; } = "meters";

        /// <summary>
        /// 坐标系
        /// </summary>
        public string CoordinateSystem { get; set; } = "Global";

        /// <summary>
        /// 是否包含时间戳
        /// </summary>
        public bool IncludeTimestamps { get; set; } = true;

        /// <summary>
        /// 是否包含元数据
        /// </summary>
        public bool IncludeMetadata { get; set; } = true;

        /// <summary>
        /// 精度（小数位数）
        /// </summary>
        public int Precision { get; set; } = 3;

        
    }

    /// <summary>
    /// 验证结果
    /// </summary>
    public class ValidationResult
    {
        /// <summary>
        /// 是否有效
        /// </summary>
        public bool IsValid { get; set; } = true;

        /// <summary>
        /// 错误信息
        /// </summary>
        public List<string> Errors { get; set; } = new List<string>();

        /// <summary>
        /// 警告信息
        /// </summary>
        public List<string> Warnings { get; set; } = new List<string>();

        /// <summary>
        /// 获取所有消息
        /// </summary>
        /// <returns>消息集合</returns>
        public IEnumerable<string> GetAllMessages()
        {
            return Errors.Concat(Warnings);
        }
    }
}
