using System.Text.Json;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging.Abstractions;
using Tiku.Api.Middleware;
using Tiku.Infrastructure.Backoffice;

namespace Tiku.IntegrationTests.Api;

public sealed class ExceptionHandlingMiddlewareTests
{
    [Theory]
    [InlineData("platform_access_denied", StatusCodes.Status403Forbidden)]
    [InlineData("role_not_found", StatusCodes.Status404NotFound)]
    [InlineData("permission_not_found", StatusCodes.Status404NotFound)]
    [InlineData("system_role_locked", StatusCodes.Status400BadRequest)]
    [InlineData("tenant_required", StatusCodes.Status400BadRequest)]
    public async Task Backoffice_exception_is_returned_as_problem_details(string code, int expectedStatus)
    {
        var context = new DefaultHttpContext();
        context.Request.Path = "/api/backoffice/test";
        context.Response.Body = new MemoryStream();
        context.TraceIdentifier = "backoffice-test-trace";
        var middleware = new ExceptionHandlingMiddleware(
            _ => throw new BackofficeException("Backoffice request failed.", code),
            NullLogger<ExceptionHandlingMiddleware>.Instance,
            new TestHostEnvironment());

        await middleware.InvokeAsync(context);

        Assert.Equal(expectedStatus, context.Response.StatusCode);
        context.Response.Body.Position = 0;
        using var document = await JsonDocument.ParseAsync(context.Response.Body);
        var root = document.RootElement;
        Assert.Equal("Backoffice request failed.", root.GetProperty("title").GetString());
        Assert.Equal(expectedStatus, root.GetProperty("status").GetInt32());
        Assert.Equal("/api/backoffice/test", root.GetProperty("instance").GetString());
        Assert.Equal(code, root.GetProperty("code").GetString());
        Assert.Equal("backoffice-test-trace", root.GetProperty("traceId").GetString());
    }

    private sealed class TestHostEnvironment : IHostEnvironment
    {
        public string EnvironmentName { get; set; } = Environments.Production;
        public string ApplicationName { get; set; } = "Tiku.IntegrationTests";
        public string ContentRootPath { get; set; } = AppContext.BaseDirectory;
        public IFileProvider ContentRootFileProvider { get; set; } = new NullFileProvider();
    }
}
