using System.Net;
using System.Text.Json;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.Configuration;

namespace Flyshot.Server.IntegrationTests;

/// <summary>
/// 锁定标准 MVC 宿主需要提供的 Swagger 与 CORS 行为，避免后续回退成只够跑通的最小配置。
/// </summary>
public sealed class HostMvcConfigurationTests(FlyshotServerFactory factory) : IClassFixture<FlyshotServerFactory>
{
    /// <summary>
    /// 验证宿主会公开标准 Swagger JSON，并且文档标题和旧 HTTP 兼容路径都能从配置和控制器路由中导出。
    /// </summary>
    [Fact]
    public async Task SwaggerDocument_ExposesConfiguredMetadataAndLegacyRoutes()
    {
        using var configuredFactory = CreateConfiguredFactory(factory);
        using var client = configuredFactory.CreateClient();

        using var response = await client.GetAsync("/swagger/v1/swagger.json");
        Assert.Equal(HttpStatusCode.OK, response.StatusCode);

        await using var responseStream = await response.Content.ReadAsStreamAsync();
        using var document = await JsonDocument.ParseAsync(responseStream);
        var root = document.RootElement;
        var paths = root.GetProperty("paths");

        Assert.Equal("3.0.1", root.GetProperty("openapi").GetString());
        Assert.Equal("Flyshot Replacement HTTP API", root.GetProperty("info").GetProperty("title").GetString());
        // OpenAPI 文档会把部分带尾斜杠的路由规范化为无尾斜杠形式，这里同时接受两种键。
        Assert.True(paths.TryGetProperty("/robot_info/", out _) || paths.TryGetProperty("/robot_info", out _));
        Assert.True(paths.TryGetProperty("/healthz", out _) || paths.TryGetProperty("/healthz/", out _));
    }

    /// <summary>
    /// 验证宿主会按配置对旧 HTTP API 路由返回标准 CORS 预检响应。
    /// </summary>
    [Fact]
    public async Task CorsPreflight_ReturnsConfiguredAllowOriginHeaders()
    {
        using var configuredFactory = CreateConfiguredFactory(factory);
        using var client = configuredFactory.CreateClient();

        using var request = new HttpRequestMessage(HttpMethod.Options, "/robot_info/");
        request.Headers.Add("Origin", "http://localhost:3000");
        request.Headers.Add("Access-Control-Request-Method", "GET");
        request.Headers.Add("Access-Control-Request-Headers", "content-type");

        using var response = await client.SendAsync(request);
        Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
        Assert.True(response.Headers.TryGetValues("Access-Control-Allow-Origin", out var allowedOrigins));
        Assert.Contains("http://localhost:3000", allowedOrigins);
        Assert.True(response.Headers.TryGetValues("Access-Control-Allow-Methods", out var allowedMethods));
        Assert.Contains("GET", string.Join(",", allowedMethods));
    }

    /// <summary>
    /// 为测试宿主注入标准 Swagger 与 CORS 配置，避免依赖开发机本地环境。
    /// </summary>
    private static WebApplicationFactory<Program> CreateConfiguredFactory(FlyshotServerFactory factory)
    {
        return factory.WithWebHostBuilder(builder =>
        {
            builder.ConfigureAppConfiguration((_, configurationBuilder) =>
            {
                configurationBuilder.AddInMemoryCollection(new Dictionary<string, string?>
                {
                    ["Swagger:Enabled"] = "true",
                    ["Swagger:DocumentName"] = "v1",
                    ["Swagger:Title"] = "Flyshot Replacement HTTP API",
                    ["Swagger:Version"] = "v1",
                    ["Cors:PolicyName"] = "LegacyHttpApi",
                    ["Cors:AllowedOrigins:0"] = "http://localhost:3000",
                    ["Cors:AllowedMethods:0"] = "GET",
                    ["Cors:AllowedMethods:1"] = "POST",
                    ["Cors:AllowedMethods:2"] = "OPTIONS",
                    ["Cors:AllowedHeaders:0"] = "content-type"
                });
            });
        });
    }
}
