using System.Diagnostics;
using System.Net.Mail;
using System.Text;

using dotenv.net;

using MesaFabApproval.API.Clients;
using MesaFabApproval.API.Services;
using MesaFabApproval.API.Utilities;
using MesaFabApproval.Models;
using MesaFabApproval.Shared.Services;

using MesaFabApprovalAPI.Services;

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.HttpLogging;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;

using NLog.Extensions.Logging;
using NLog.Web;

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);

DotEnv.Load();

builder.Logging.ClearProviders();
builder.Logging.SetMinimumLevel(LogLevel.Trace);
builder.Logging.AddNLog();

/*builder.Services.AddHttpLogging(o => {
    o.LoggingFields = HttpLoggingFields.All;
    o.RequestHeaders.Add("bearer");
    o.MediaTypeOptions.AddText("application/javascript");
    o.RequestBodyLogLimit = 4096;
    o.ResponseBodyLogLimit = 4096;
    o.CombineLogs = true;
});*/

builder.Services.AddMemoryCache();

if (Debugger.IsAttached) {
    string? jwtIssuer = Environment.GetEnvironmentVariable("FabApprovalJwtIssuer");
    if (string.IsNullOrEmpty(jwtIssuer)) {
        AppSettings.SetEnvironmentVariables(builder);
    }
}

AppSettings appSettings = AppSettings.LoadEnvironmentVariables();
builder.Services.AddSingleton(_ => appSettings);

builder.Services.AddAuthentication(options => {
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options => {
    options.RequireHttpsMetadata = false;
    options.SaveToken = true;
    options.TokenValidationParameters = new TokenValidationParameters {
        ValidateIssuerSigningKey = true,
        ValidIssuer = appSettings.JwtIssuer,
        ValidateAudience = false,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(appSettings.JwtKey)),
        ClockSkew = TimeSpan.Zero
    };
});

builder.Services.AddAuthorization(options => {
    options.DefaultPolicy = new AuthorizationPolicyBuilder()
                                .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
                                .RequireAuthenticatedUser()
                                .Build();
});

builder.Services.AddHttpClient();

builder.Services.AddCors(options => {
    options.AddDefaultPolicy(options => {
        options.AllowAnyOrigin();
        options.AllowAnyMethod();
        options.AllowAnyHeader();
    });
});

builder.Services.AddScoped<IDbConnectionService, DbConnectionService>();
builder.Services.AddScoped<IDalService, DalService>();
builder.Services.AddScoped<SmtpClient>((serviceProvider) => {
    return new SmtpClient("mailrelay-external.infineon.com");
});
builder.Services.AddScoped<ISmtpClientWrapper, SmtpClientWrapper>();
builder.Services.AddScoped<ICustomerService, CustomerService>();
builder.Services.AddScoped<ICAService, CAService>();
builder.Services.AddScoped<IECNService, ECNService>();
builder.Services.AddScoped<ISmtpService, SmtpService>();
builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddScoped<IMonInWorkerClient, MonInWorkerClient>();
builder.Services.AddScoped<IMonInUtils, MonInUtils>();
builder.Services.AddScoped<IAuthenticationService, AuthenticationService>();
builder.Services.AddScoped<IMRBService, MRBService>();
builder.Services.AddScoped<IPCRBService, PCRBService>();
builder.Services.AddScoped<IApprovalService, ApprovalService>();

builder.Services.AddControllers();

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c => {
    c.SwaggerDoc("v1", new OpenApiInfo {
        Title = "Mesa Fab Approval API",
        Version = "v1"
    });
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme {
        In = ParameterLocation.Header,
        Description = "Please insert JWT with Bearer into field",
        Name = "Authorization",
        Type = SecuritySchemeType.ApiKey
    });
    c.AddSecurityRequirement(new OpenApiSecurityRequirement {
   {
     new OpenApiSecurityScheme
     {
       Reference = new OpenApiReference
       {
         Type = ReferenceType.SecurityScheme,
         Id = "Bearer"
       }
      },
      new string[] { }
    }
  });
});

WebApplication app = builder.Build();

app.UseCors();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) {
    app.UseSwagger();
    app.UseSwaggerUI();
}

// app.UseHttpLogging();

app.UseAuthentication();

app.UseAuthorization();

app.MapControllers();

app.Run();

NLog.LogManager.Flush();
NLog.LogManager.Shutdown();