
using Microsoft.IdentityModel.Tokens;
using System.Text;
using Microsoft.OpenApi.Models;
using System.Reflection;
using System.Text.Json.Serialization;
using bdAntifraude.dbcontext;
using SwaggerAntifraude.Middlewares;
using Microsoft.AspNetCore.Authentication.JwtBearer;

var builder = WebApplication.CreateBuilder(args);

// 1. Configuración de Servicios

// a. Configurar servicios de controladores
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
    options.SuppressModelStateInvalidFilter = true; // Desactiva la validación automática del estado del modelo
})
.AddJsonOptions(options =>
{
    options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});

// b. Configuración de JWT
var jwtSettings = builder.Configuration.GetSection("Jwt");
var keyString = jwtSettings["Key"];
if (string.IsNullOrEmpty(keyString))
{
    throw new ArgumentNullException("JWT Key is not configured.");
}
var key = Encoding.UTF8.GetBytes(keyString);

if (!double.TryParse(jwtSettings["ExpiresInMinutes"], out double expiresInMinutes))
{
    expiresInMinutes = 60; // Valor por defecto
}

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = jwtSettings["Issuer"],
        ValidAudience = jwtSettings["Audience"],
        IssuerSigningKey = new SymmetricSecurityKey(key)
    };
});

builder.WebHost.ConfigureKestrel(options =>
{
    options.ConfigureHttpsDefaults(httpsOptions =>
    {
        httpsOptions.ClientCertificateMode =
            Microsoft.AspNetCore.Server.Kestrel.Https.ClientCertificateMode.AllowCertificate;

        // (Opcional, en pruebas)
        httpsOptions.AllowAnyClientCertificate();
    });
});





// c. Definir Políticas de Autorización
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("SupervisorPolicy", policy => policy.RequireRole("Supervisor"));
    options.AddPolicy("LecturaPolicy", policy => policy.RequireRole("Lectura", "Supervisor"));
});

// d. Configurar Swagger con soporte para JWT
builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "Swagger OAAF API", Version = "v1" });

    // Definir el esquema de seguridad JWT
    var securityScheme = new OpenApiSecurityScheme
    {
        Name = "Authorization",
        Description = "Ingrese 'Bearer' seguido de su token en el campo de texto.\n\nEjemplo: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6...'",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.ApiKey,
        Scheme = "Bearer",
        BearerFormat = "JWT"
    };

    c.AddSecurityDefinition("Bearer", securityScheme);


    var securityRequirement = new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = "Bearer"
                }
            },
            new string[] {}
        }
    };

    c.AddSecurityRequirement(securityRequirement);

    // Incluir comentarios XML para Swagger
    var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
    if (File.Exists(xmlPath))
    {
        c.IncludeXmlComments(xmlPath);
    }
});

// Inicializar las cadenas de conexión
var connectionStrings = builder.Configuration.GetSection("ConnectionStrings");
var writeConnectionString = connectionStrings["WriteConnection"];
var readOnlyConnectionString = connectionStrings["ReadOnlyConnection"];

if (string.IsNullOrEmpty(writeConnectionString) || string.IsNullOrEmpty(readOnlyConnectionString))
{
    throw new ArgumentNullException("Las cadenas de conexión no están configuradas correctamente.");
}

tsGestionAntifraude.EstableceCBD(writeConnectionString, readOnlyConnectionString);

var app = builder.Build();

// 2. Configuración del Pipeline HTTP

// a. Middleware de Excepciones
app.UseMiddleware<ExceptionMiddleware>();

// b. Habilitar Swagger solo en Desarrollo
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "SwaggerCamcue API V1");
        c.RoutePrefix = string.Empty; // Swagger en la raíz
    });
}

//app.UseHttpsRedirection();

// c. Configurar CORS (Opcional)
app.UseCors("AllowSpecificOrigin");

// d. Autenticación y Autorización
app.UseAuthentication();
app.UseAuthorization();

// e. Mapear Controladores
app.MapControllers();

// f. Ejecutar la Aplicación
app.Run();
