using Flyshot.ControllerClientCompat;
using Flyshot.Server.Host;
using Flyshot.Server.Host.Middleware;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using NLog.Web;
using Swashbuckle.AspNetCore.SwaggerGen;

// NLog: 在 ASP.NET Core 启动前完成配置加载，确保最早期的日志也能被捕获。
NLog.LogManager.Setup().LoadConfigurationFromAppSettings();
var logger = NLog.LogManager.GetCurrentClassLogger();

try
{
    logger.Info("Flyshot Server Host 启动中...");

    var builder = WebApplication.CreateBuilder(args);

    // NLog: 替换默认日志提供者为 NLog，清除其他 Provider 避免重复输出。
    builder.Logging.ClearProviders();
    builder.Host.UseNLog();

    builder.Services.Configure<HostSwaggerOptions>(builder.Configuration.GetSection("Swagger"));
    builder.Services.Configure<HostCorsOptions>(builder.Configuration.GetSection("Cors"));
    builder.Services.AddControllerClientCompat(builder.Configuration);
    builder.Services.AddControllers();
    builder.Services.AddEndpointsApiExplorer();

    var swaggerOptions = builder.Configuration.GetSection("Swagger").Get<HostSwaggerOptions>() ?? new HostSwaggerOptions();
    builder.Services.AddSwaggerGen(options =>
    {
        options.SwaggerDoc(swaggerOptions.DocumentName, new OpenApiInfo
        {
            Title = swaggerOptions.Title,
            Version = swaggerOptions.Version
        });

        // 把控制器与 DTO 上的 /// summary 注释纳入 OpenAPI 文档；调试页据此渲染端点标题。
        var xmlDocumentationPath = Path.Combine(AppContext.BaseDirectory, $"{typeof(Program).Assembly.GetName().Name}.xml");
        if (File.Exists(xmlDocumentationPath))
        {
            options.IncludeXmlComments(xmlDocumentationPath, includeControllerXmlComments: true);
        }
    });

    var corsOptions = builder.Configuration.GetSection("Cors").Get<HostCorsOptions>() ?? new HostCorsOptions();
    builder.Services.AddCors(options =>
    {
        options.AddPolicy(corsOptions.PolicyName, policyBuilder =>
        {
            // 兼容本地调试时最常见的任意源配置，同时保留显式白名单模式。
            if (corsOptions.AllowedOrigins.Length == 1 && string.Equals(corsOptions.AllowedOrigins[0], "*", StringComparison.Ordinal))
            {
                policyBuilder.AllowAnyOrigin();
            }
            else
            {
                policyBuilder.WithOrigins(corsOptions.AllowedOrigins);
            }

            if (corsOptions.AllowedMethods.Length == 1 && string.Equals(corsOptions.AllowedMethods[0], "*", StringComparison.Ordinal))
            {
                policyBuilder.AllowAnyMethod();
            }
            else
            {
                policyBuilder.WithMethods(corsOptions.AllowedMethods);
            }

            if (corsOptions.AllowedHeaders.Length == 1 && string.Equals(corsOptions.AllowedHeaders[0], "*", StringComparison.Ordinal))
            {
                policyBuilder.AllowAnyHeader();
            }
            else
            {
                policyBuilder.WithHeaders(corsOptions.AllowedHeaders);
            }
        });
    });

    var app = builder.Build();

    var resolvedSwaggerOptions = app.Services.GetRequiredService<IOptions<HostSwaggerOptions>>().Value;
    var resolvedCorsOptions = app.Services.GetRequiredService<IOptions<HostCorsOptions>>().Value;

    if (resolvedSwaggerOptions.Enabled)
    {
        app.UseSwagger(options =>
        {
            options.RouteTemplate = resolvedSwaggerOptions.JsonRouteTemplate;
        });

        app.UseSwaggerUI(options =>
        {
            options.RoutePrefix = resolvedSwaggerOptions.RoutePrefix;
            options.SwaggerEndpoint(
                $"/swagger/{resolvedSwaggerOptions.DocumentName}/swagger.json",
                $"{resolvedSwaggerOptions.Title} {resolvedSwaggerOptions.Version}");
            options.DocumentTitle = resolvedSwaggerOptions.Title;
        });
    }

    app.UseCors(resolvedCorsOptions.PolicyName);
    app.UseStaticFiles();

    // 注册 HTTP 请求/响应日志中间件，记录所有 API 调用的输入输出。
    app.UseMiddleware<RequestResponseLoggingMiddleware>();

    app.MapControllers();

    logger.Info("Flyshot Server Host 已就绪，开始监听请求。");
    app.Run();
}
catch (Exception exception)
{
    logger.Error(exception, "Flyshot Server Host 启动失败。");
    throw;
}
finally
{
    NLog.LogManager.Shutdown();
}

public partial class Program;
