using System.Net;
using System.Net.Http.Json;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.AdminUI.Api;

namespace ZB.MOM.WW.OtOpcUa.Host.IntegrationTests;

/// <summary>
/// End-to-end test of the headless deploy REST endpoint over real HTTP against an in-process admin
/// node: an unauthenticated/wrong-key POST is rejected, and a correctly-keyed POST triggers a real
/// deployment through the same AdminOperations singleton the AdminUI button uses.
/// </summary>
public sealed class DeployApiE2eTests
{
    private static CancellationToken Ct => TestContext.Current.CancellationToken;

    /// <summary>Verifies the deploy endpoint enforces the API key and accepts a correctly-keyed call.</summary>
    [Fact]
    public async Task Deploy_endpoint_enforces_api_key_and_triggers_a_deployment()
    {
        await using var harness = await TwoNodeClusterHarness.StartAsync();
        using var http = new HttpClient { BaseAddress = new Uri(harness.NodeABaseAddress) };

        // No key → 401
        var noKey = await http.PostAsJsonAsync("/api/deployments", new { createdBy = "ci" }, Ct);
        noKey.StatusCode.ShouldBe(HttpStatusCode.Unauthorized);

        // Wrong key → 401
        (await SendWithKeyAsync(http, "wrong-key")).StatusCode.ShouldBe(HttpStatusCode.Unauthorized);

        // Correct key → 202 Accepted (an empty config still composes + seals an empty deployment)
        var accepted = await SendWithKeyAsync(http, TwoNodeClusterHarness.HarnessDeployApiKey);
        accepted.StatusCode.ShouldBe(HttpStatusCode.Accepted);

        var payload = await accepted.Content.ReadFromJsonAsync<DeployApiEndpoints.DeployResponse>(Ct);
        payload.ShouldNotBeNull();
        payload!.Outcome.ShouldBe("Accepted");
        payload.DeploymentId.ShouldNotBeNull();
    }

    private static Task<HttpResponseMessage> SendWithKeyAsync(HttpClient http, string key)
    {
        var req = new HttpRequestMessage(HttpMethod.Post, "/api/deployments")
        {
            Content = JsonContent.Create(new { createdBy = "ci-bot" }),
        };
        req.Headers.Add(DeployApiEndpoints.ApiKeyHeader, key);
        return http.SendAsync(req, Ct);
    }
}
