using System;
using System.Linq;
using TrajectoryPlanningVisualization;

namespace TrajectoryPlanningVisualizationVerificationHost;

internal static class RuntimeChecks
{
    public static void Run()
    {
        KeepsOnlyTheLatestFrame();
        KeepsBoundedDeduplicatedCycleHistory();
        SerializesStableCamelCaseJson();
        RejectsInvalidOptions();
    }

    private static void KeepsOnlyTheLatestFrame()
    {
        var store = new LatestVisualizationFrameStore();
        store.Publish(Snap(1));
        store.Publish(Snap(2));

        Verification.True(store.TryReadAfter(0, out VisualizationFrame frame), "latest frame exists");
        Verification.Equal(2L, frame.Snapshot.Sequence, "latest frame replaces old frame");
        Verification.True(!store.TryReadAfter(frame.Version, out _), "same frame is not replayed");
    }

    private static void KeepsBoundedDeduplicatedCycleHistory()
    {
        var history = new BoundedCycleHistory(2);
        history.Add(Cycle(1));
        history.Add(Cycle(2));
        history.Add(Cycle(3));
        history.Add(Cycle(3));

        Verification.Equal("2|3", string.Join("|", history.Snapshot().Select(x => x.CycleVersion)),
            "history is bounded and deduplicated");
    }

    private static void SerializesStableCamelCaseJson()
    {
        string json = VisualizationJson.Serialize(Snap(2));
        Verification.True(json.Contains("\"sessionStateChinese\"") && json.Contains("\"observedAtUtc\""),
            "JSON uses stable camel case names");
    }

    private static void RejectsInvalidOptions()
    {
        Verification.Throws<ArgumentOutOfRangeException>(
            () => new PlanningVisualizationOptions { Port = -1 }.CreateValidatedSnapshot(),
            "options reject a negative port");
        Verification.Throws<ArgumentOutOfRangeException>(
            () => new PlanningVisualizationOptions { RefreshRateHz = 0 }.CreateValidatedSnapshot(),
            "options reject a zero refresh rate");
        Verification.Throws<ArgumentOutOfRangeException>(
            () => new PlanningVisualizationOptions { HistoryCycleLimit = 0 }.CreateValidatedSnapshot(),
            "options reject a zero history limit");
        Verification.Throws<ArgumentOutOfRangeException>(
            () => new PlanningVisualizationOptions { Port = 65536 }.CreateValidatedSnapshot(),
            "options reject a port above the TCP range");

        var snapshot = new PlanningVisualizationOptions().CreateValidatedSnapshot();
        Verification.Equal(0, snapshot.Port, "default port is automatic");
        Verification.Equal(10, snapshot.RefreshRateHz, "default refresh rate is 10 Hz");
        Verification.Equal(60, snapshot.HistoryCycleLimit, "default history is bounded to 60 cycles");
        Verification.Equal(2, snapshot.MaximumClients, "maximum clients is fixed at two");
    }

    private static PlanningVisualizationDynamicSnapshot Snap(long sequence)
    {
        return new PlanningVisualizationDynamicSnapshot(
            sequence,
            DateTimeOffset.Parse("2026-08-06T00:00:00+00:00").AddSeconds(sequence),
            "运行中",
            0,
            "forward",
            new VisualizationPose(1d, 2d, 0d),
            Array.Empty<VisualizationPolyline>(),
            Array.Empty<VisualizationMarker>(),
            Array.Empty<VisualizationChart>(),
            Array.Empty<VisualizationValue>(),
            Cycle(sequence));
    }

    private static VisualizationCycleSummary Cycle(long cycleVersion)
    {
        return new VisualizationCycleSummary(
            cycleVersion,
            DateTimeOffset.Parse("2026-08-06T00:00:00+00:00").AddSeconds(cycleVersion),
            "成功",
            true,
            2.5d,
            0,
            "forward",
            "rolling",
            "none",
            null,
            null,
            "");
    }
}
