using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json.Linq;

namespace NavisworksTransport.UnitTests.Integration
{
    /// <summary>
    /// 路径编辑集成测试（覆盖计划 T11）。
    ///
    /// 验证 PathPlanningManager 编辑链路：
    /// - 删除路径点（remove-point：点数递减）
    /// - 更新路径点位置（update-point：坐标更新）
    /// - 正交化（orthogonalize）
    /// - 去除矩形环（remove-loops）
    ///
    /// 使用独立导入的临时路径，避免影响标准测试路径。
    /// </summary>
    [TestClass]
    [TestCategory("NavisworksIntegration")]
    public class PathEditingAutomationTests
    {
        private const string RouteName = "路径编辑_测试";

        [TestMethod]
        [Timeout(120000)]
        public async Task EditRoute_RemoveUpdateOrthogonalize_Work()
        {
            using (var client = new NavisworksTestAutomationClient())
            {
                await client.EnsureServiceReadyAsync(TimeSpan.FromSeconds(90)).ConfigureAwait(false);

                string tempDir = Path.Combine(Path.GetTempPath(), "NavisworksTransportIntegrationTests", Guid.NewGuid().ToString("N"));
                Directory.CreateDirectory(tempDir);
                try
                {
                    // 1. 导入 3 点测试路径
                    string filePath = Path.Combine(tempDir, "edit-route.json");
                    File.WriteAllText(filePath, BuildEditRouteJson(), new UTF8Encoding(false));
                    JObject importResponse = await client.ImportRouteFileAsync(filePath, overwrite: true).ConfigureAwait(false);
                    Assert.IsTrue(importResponse.Value<bool>("ok"), "导入编辑路径失败: " + (string)importResponse["error"]);
                    Assert.AreEqual(3, (int)((JArray)importResponse["data"]["routes"])[0]["pointCount"], "初始点数应为 3");

                    // 2. 删除中间点（index=1）
                    JObject removeResponse = await client.EditRouteAsync("remove-point", RouteName, pointIndex: 1).ConfigureAwait(false);
                    Assert.IsTrue(removeResponse.Value<bool>("ok"), "删除路径点失败: " + (string)removeResponse["error"]);
                    Assert.AreEqual(2, (int)removeResponse["data"]["pointCount"], "删除后点数应为 2");

                    // 3. 更新起点位置
                    JObject updateResponse = await client.EditRouteAsync(
                        "update-point", RouteName,
                        pointIndex: 0, x: -204.608, y: 14.833, z: 20.0).ConfigureAwait(false);
                    Assert.IsTrue(updateResponse.Value<bool>("ok"), "更新路径点失败: " + (string)updateResponse["error"]);
                    JArray updatedPoints = (JArray)updateResponse["data"]["points"];
                    JObject updatedStart = (JObject)updatedPoints[0]["position"];
                    Assert.AreEqual(20.0, (double)updatedStart["z"], 1e-2, "更新后的 Z 坐标不匹配");

                    // 4. 正交化
                    JObject orthogonalizeResponse = await client.EditRouteAsync("orthogonalize", RouteName).ConfigureAwait(false);
                    Assert.IsTrue(orthogonalizeResponse.Value<bool>("ok"), "正交化失败: " + (string)orthogonalizeResponse["error"]);
                    Assert.IsTrue((int)orthogonalizeResponse["data"]["pointCount"] >= 2, "正交化后点数应 >= 2");

                    // 5. 去除矩形环
                    JObject removeLoopsResponse = await client.EditRouteAsync("remove-loops", RouteName).ConfigureAwait(false);
                    Assert.IsTrue(removeLoopsResponse.Value<bool>("ok"), "去除矩形环失败: " + (string)removeLoopsResponse["error"]);
                }
                finally
                {
                    SafeDelete(tempDir);
                }
            }
        }

        private static string BuildEditRouteJson()
        {
            return string.Format(
                System.Globalization.CultureInfo.InvariantCulture,
                @"{{""PathPlanningData"":{{""version"":""1.0"",""generator"":""integration-test"",""timestamp"":""2026-08-04T21:30:00"",""ProjectInfo"":{{""name"":""test"",""description"":""test"",""units"":""meters"",""coordinateSystem"":""Global""}},""Routes"":[{{""id"":""edit-route-{0}"",""name"":""{1}"",""description"":"""",""pathType"":""Ground"",""totalLength"":20.0,""objectLimits"":{{""maxLength"":0,""maxWidth"":0,""maxHeight"":0,""safetyMargin"":0}},""gridSize"":1.0,""liftHeight"":0.0,""created"":""2026-08-04T21:30:00"",""points"":[{{""id"":""er-p1"",""name"":""start"",""type"":""StartPoint"",""index"":0,""x"":-204.608,""y"":14.833,""z"":19.250,""created"":""2026-08-04T21:30:00""}},{{""id"":""er-p2"",""name"":""mid"",""type"":""WayPoint"",""index"":1,""x"":-206.608,""y"":14.833,""z"":18.250,""created"":""2026-08-04T21:30:00""}},{{""id"":""er-p3"",""name"":""end"",""type"":""EndPoint"",""index"":2,""x"":-208.608,""y"":14.833,""z"":17.250,""created"":""2026-08-04T21:30:00""}}]}}]}}}}",
                Guid.NewGuid().ToString("N"),
                RouteName);
        }

        private static void SafeDelete(string directory)
        {
            if (!Directory.Exists(directory))
            {
                return;
            }

            try
            {
                Directory.Delete(directory, true);
            }
            catch
            {
            }
        }
    }
}
