using System.Net;
using System.Net.Http.Json;

namespace CashLineERP.Api.Tests;

public sealed class SmokeTests : IClassFixture<ApiTestFactory>
{
    private readonly HttpClient _client;

    public SmokeTests(ApiTestFactory factory)
    {
        _client = factory.CreateClient();
    }

    [Fact]
    public async Task Build_Info_Is_Public_And_Returns_Service_Metadata()
    {
        var response = await _client.GetAsync("/api/v1/build-info");

        Assert.True(response.IsSuccessStatusCode, await response.Content.ReadAsStringAsync());

        var payload = await response.Content.ReadFromJsonAsync<Dictionary<string, object>>();
        Assert.NotNull(payload);
        Assert.Equal("CashLineERP.Api", payload!["service"]?.ToString());
        Assert.True(payload.ContainsKey("environment"));
        Assert.True(payload.ContainsKey("build"));
        Assert.Equal("v1", payload["apiVersion"]?.ToString());
        Assert.Equal("V1_CONTROLLED_BASELINE", payload["releaseChannel"]?.ToString());
        Assert.True(payload.ContainsKey("releaseVersion"));
        Assert.True(payload.ContainsKey("changelogDoc"));
        Assert.True(payload.ContainsKey("latestReleaseNotesDoc"));
        Assert.True(payload.ContainsKey("deprecationPolicyDoc"));
        Assert.Equal("0", payload["activeDeprecationCount"]?.ToString());
    }

    [Fact]
    public async Task Health_And_Baseline_Read_Endpoints_Return_Success()
    {
        await _client.AuthenticateAsInternalAsync();

        var health = await _client.GetAsync("/health");
        var profile = await _client.GetAsync("/api/v1/auth/me");
        var queue = await _client.GetAsync("/api/v1/workflow/queue");
        var parties = await _client.GetAsync("/api/v1/parties");

        Assert.True(health.IsSuccessStatusCode, await health.Content.ReadAsStringAsync());
        Assert.True(profile.IsSuccessStatusCode, await profile.Content.ReadAsStringAsync());
        Assert.True(queue.IsSuccessStatusCode, await queue.Content.ReadAsStringAsync());
        Assert.True(parties.IsSuccessStatusCode, await parties.Content.ReadAsStringAsync());

        var healthPayload = await health.Content.ReadFromJsonAsync<Dictionary<string, object>>();
        Assert.NotNull(healthPayload);
        Assert.True(healthPayload!.ContainsKey("environment"));
    }

    [Fact]
    public async Task Protected_Api_Routes_Require_Authentication()
    {
        var response = await _client.GetAsync("/api/v1/iam/roles");

        Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
    }

    [Fact]
    public async Task External_Party_Routes_Enforce_Party_Scoping()
    {
        await _client.AuthenticateAsSupplierAsync();

        var response = await _client.GetAsync("/api/v1/external/parties/2/orders");

        Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
    }

    [Fact]
    public async Task Auth_Me_Returns_Profile_For_External_And_Internal_Users()
    {
        await _client.AuthenticateAsSupplierAsync();

        var externalResponse = await _client.GetAsync("/api/v1/auth/me");
        Assert.True(externalResponse.IsSuccessStatusCode, await externalResponse.Content.ReadAsStringAsync());

        var externalPayload = await externalResponse.Content.ReadFromJsonAsync<Dictionary<string, object>>();
        Assert.NotNull(externalPayload);
        Assert.Equal("EXTERNAL", externalPayload!["userType"]?.ToString());

        await _client.AuthenticateAsFinanceCheckerAsync();

        var internalResponse = await _client.GetAsync("/api/v1/auth/me");
        Assert.True(internalResponse.IsSuccessStatusCode, await internalResponse.Content.ReadAsStringAsync());

        var internalPayload = await internalResponse.Content.ReadFromJsonAsync<Dictionary<string, object>>();
        Assert.NotNull(internalPayload);
        Assert.Equal("INTERNAL", internalPayload!["userType"]?.ToString());
    }
}
