using Microsoft.AspNetCore.Authorization;
using Serilog;
using Scalar.AspNetCore;
using SIGCM2.Api.Authorization;
using SIGCM2.Api.Filters;
using SIGCM2.Api.HealthChecks;
using SIGCM2.Api.Json;
using SIGCM2.Api.Middleware;
using SIGCM2.Application;
using SIGCM2.Infrastructure;
using SIGCM2.Infrastructure.Audit.Jobs;

// Bootstrap logger — before DI is built
Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .CreateBootstrapLogger();

Log.Information("Starting SIGCM2 API");

var builder = WebApplication.CreateBuilder(args);

// Serilog — reads from appsettings.json "Serilog" section
builder.Host.UseSerilog((ctx, lc) => lc
    .ReadFrom.Configuration(ctx.Configuration));

// Application + Infrastructure DI
builder.Services.AddApplication();
builder.Services.AddInfrastructure(builder.Configuration);

// UDT-010: Quartz.NET + 3 audit maintenance jobs (partition, retention, integrity).
// Disabled in Testing environment to keep integration tests deterministic.
if (!builder.Environment.IsEnvironment("Testing"))
    builder.Services.AddAuditMaintenance(builder.Configuration);

// Authorization — handler lives in Api layer; DO NOT move to Infrastructure DI
builder.Services.AddAuthorization();
builder.Services.AddScoped<IAuthorizationHandler, PermissionAuthorizationHandler>();
builder.Services.AddSingleton<IAuthorizationMiddlewareResultHandler, ForbiddenProblemDetailsHandler>();

// Controllers with exception filter + JSON options
// UDT-011: DateOnlyJsonConverter ensures Cat2 date fields serialize as "yyyy-MM-dd"
// and never as "2026-05-01T00:00:00" or with a UTC "Z" suffix.
builder.Services.AddControllers(opts =>
{
    opts.Filters.Add<ExceptionFilter>();
}).AddJsonOptions(jsonOpts =>
{
    jsonOpts.JsonSerializerOptions.Converters.Add(new DateOnlyJsonConverter());
});

// OpenAPI / Scalar
builder.Services.AddOpenApi();

// UDT-010: Audit infrastructure health check
builder.Services.AddHealthChecks()
    .AddCheck<AuditHealthCheck>("audit", tags: new[] { "audit" });

// CORS
var allowedOrigins = builder.Configuration
    .GetSection("Cors:AllowedOrigins")
    .Get<string[]>() ?? [];

builder.Services.AddCors(opts =>
{
    opts.AddDefaultPolicy(policy =>
        policy.WithOrigins(allowedOrigins)
              .AllowAnyHeader()
              .AllowAnyMethod());
});

var app = builder.Build();

// Middleware pipeline
app.UseSerilogRequestLogging();

if (app.Environment.IsDevelopment() || app.Environment.IsEnvironment("Testing"))
{
    app.MapOpenApi();
    app.MapScalarApiReference(opts =>
    {
        opts.Title = "SIGCM2 API";
    });
}

app.UseHttpsRedirection();
app.UseCors();
// UDT-010: correlation id + ip/ua capture runs BEFORE auth so anonymous requests
// still get a correlation id and so logs can tie pre-auth events to the request.
app.UseMiddleware<CorrelationIdMiddleware>();
app.UseAuthentication();
// UDT-010: actor extraction runs AFTER auth to read the JWT sub claim.
app.UseMiddleware<AuditActorMiddleware>();
app.UseAuthorization();
app.MapControllers();

// UDT-010: /health/audit returns the audit check status (public but sparse data).
app.MapHealthChecks("/health/audit", new Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions
{
    Predicate = r => r.Tags.Contains("audit"),
});

app.Run();

// Exposed for WebApplicationFactory in integration tests
public partial class Program { }
