using LSFE.Domain.Contracts;
using LSFE.Domain.Contracts.Doctor;
using LSFE.Domain.Contracts.Maintenance;
using LSFE.Domain.Contracts.Planning;
using LSFE.Domain.Contracts.Reports;
using LSFE.Domain.Contracts.TimeKeeping;
using LSFE.Domain.Services;
using LSFE.Domain.Services.Account;
using LSFE.Domain.Services.Doctor;
using LSFE.Domain.Services.Maintenance;
using LSFE.Domain.Services.Planning;
using LSFE.Domain.Services.Reports;
using LSFE.Domain.Services.Security;
using LSFE.Domain.Services.TimeKeeping;
using LSFE.Infrastructure.Database;
using LSFE.Infrastructure.Entities;
using LSFE.Infrastructure.Entities.Auth;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using System.Text;

var builder = WebApplication.CreateBuilder(args);

// Add DbContext
builder.Services.AddDbContext<LSFEDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddIdentity<AppsUsers, Role>()
    .AddEntityFrameworkStores<LSFEDbContext>()
    .AddDefaultTokenProviders();

// Add JWT Authentication
builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    /* options.Events = new JwtBearerEvents
     {
         OnAuthenticationFailed = context =>
         {
             Console.WriteLine($"Authentication failed: {context.Exception.Message}");
             return Task.CompletedTask;
         },
         OnTokenValidated = context =>
         {
             Console.WriteLine("Token validated successfully");
             return Task.CompletedTask;
         }
     };*/
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidAudience = builder.Configuration["JWT:ValidAudience"],
        ValidIssuer = builder.Configuration["JWT:ValidIssuer"],
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["JWT:Secret"] ?? "none")
        ),
        ClockSkew = TimeSpan.Zero
    };
});

builder.Services.AddAuthorization();

builder.Services.AddMemoryCache();
builder.Services.AddScoped<IRoleAuthorizationCache, RoleAuthorizationCache>();

builder.Services.AddScoped<IUnitOfWork, UnitOfWork>();
builder.Services.AddScoped<ExcelInventoryService>();
builder.Services.AddScoped<IErrorLogger, ErrorLogger>();
builder.Services.AddScoped<IDoctorRepo, DoctorRepo>();
builder.Services.AddScoped<IPlanningRepo, PlanningRepo>();
builder.Services.AddScoped<IReportsRepo, ReportsRepo>();
builder.Services.AddScoped<IAttendanceRepo, AttendanceRepo>();
builder.Services.AddScoped<INavigationService, NavigationService>();
builder.Services.AddScoped(typeof(IMaintenanceRepo<>), typeof(MaintenanceRepo<>));

builder.Services.AddScoped<IAccountService, AccountService>();

// Add Controllers & Swagger
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "LLOYD API V1", Version = "v1" });
});
builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowAnyOrigin",
        corsBuilder =>
        {
            corsBuilder.WithOrigins(
                       "https://vamslerultramed.com",
                       "https://www.vamslerultramed.com",
                       "http://localhost:5173"
                   )
                   .AllowAnyMethod()
                   .AllowAnyHeader()
                   .AllowCredentials();
        });
});
var app = builder.Build();

app.UseSwagger();
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "LLOYD API V1");
});
app.UseCors("AllowAnyOrigin");
app.UseHttpsRedirection();
app.UseAuthentication();

app.UseAuthorization();

app.MapControllers();
app.Run();