using Microsoft.AspNetCore.Http;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.AdminUI.Api;
using ZB.MOM.WW.OtOpcUa.Commons.Messages.Admin;
using ZB.MOM.WW.OtOpcUa.Commons.Types;

namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.Api;

/// <summary>Unit tests for the pure helpers behind the headless deploy REST endpoint —
/// <see cref="DeployApiEndpoints.IsAuthorized"/> (fixed-time API-key check) and
/// <see cref="DeployApiEndpoints.ToResult"/> (outcome → HTTP status mapping).</summary>
public sealed class DeployApiEndpointsTests
{
    // ── IsAuthorized ────────────────────────────────────────────────────────────

    /// <summary>Verifies the exact configured key authorizes.</summary>
    [Fact]
    public void IsAuthorized_true_for_matching_key()
        => DeployApiEndpoints.IsAuthorized("s3cret", "s3cret").ShouldBeTrue();

    /// <summary>Verifies a wrong key is rejected.</summary>
    [Fact]
    public void IsAuthorized_false_for_wrong_key()
        => DeployApiEndpoints.IsAuthorized("nope", "s3cret").ShouldBeFalse();

    /// <summary>Verifies a missing/empty provided key is rejected.</summary>
    [Theory]
    [InlineData(null)]
    [InlineData("")]
    public void IsAuthorized_false_for_missing_provided_key(string? provided)
        => DeployApiEndpoints.IsAuthorized(provided, "s3cret").ShouldBeFalse();

    /// <summary>Verifies that when no key is configured nothing authorizes (endpoint stays closed).</summary>
    [Theory]
    [InlineData(null)]
    [InlineData("")]
    public void IsAuthorized_false_when_no_key_configured(string? configured)
        => DeployApiEndpoints.IsAuthorized("anything", configured).ShouldBeFalse();

    // ── ToResult ────────────────────────────────────────────────────────────────

    /// <summary>Verifies each deployment outcome maps to the right HTTP status.</summary>
    [Theory]
    [InlineData(StartDeploymentOutcome.Accepted, StatusCodes.Status202Accepted)]
    [InlineData(StartDeploymentOutcome.NoChanges, StatusCodes.Status200OK)]
    [InlineData(StartDeploymentOutcome.AnotherDeploymentInFlight, StatusCodes.Status409Conflict)]
    [InlineData(StartDeploymentOutcome.Rejected, StatusCodes.Status422UnprocessableEntity)]
    public void ToResult_maps_outcome_to_status(StartDeploymentOutcome outcome, int expectedStatus)
    {
        var result = DeployApiEndpoints.ToResult(
            new StartDeploymentResult(outcome, DeploymentId: null, RevisionHash: null,
                Message: "x", CorrelationId: CorrelationId.NewId()));

        result.ShouldBeAssignableTo<IStatusCodeHttpResult>();
        ((IStatusCodeHttpResult)result).StatusCode.ShouldBe(expectedStatus);
    }
}
