using MTWorkHR.Application;
using MTWorkHR.Infrastructure;
using Microsoft.EntityFrameworkCore;
using MTWorkHR.Core;
using MTWorkHR.Core.Global;
using MTWorkHR.Application.Middlewares;
using MTWorkHR.Application.Services.Interfaces;
using MTWorkHR.Application.Filters;
using MTWorkHR.Application.StartupService;
using Microsoft.AspNetCore.Mvc;
using MTWorkHR.Infrastructure.DBContext;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.OpenApi.Models;
using MTWorkHR.API.Swagger;
using Azure.Storage.Blobs;
using Moq;


using Microsoft.Extensions.DependencyInjection;
using DevExpress.AspNetCore;
using DevExpress.XtraCharts;
using DevExpress.XtraReports.Web.Extensions;
using DevExpress.AspNetCore.Reporting;
using MTWorkHR.Infrastructure.Reports;
using MTWorkHR.API.Chat;
using Microsoft.AspNetCore.SignalR;
using MTWorkHR.Application.Services.Payment;
using Microsoft.AspNetCore.Diagnostics;
using DevExpress.DataAccess.Native.Web;

var builder = WebApplication.CreateBuilder(args);

if (OperatingSystem.IsLinux())
{
    builder.Configuration.AddJsonFile("appsettings.Linux.json", optional: true, reloadOnChange: true);
}



var config = new AppSettingsConfiguration();
// Add services to the container.
builder.Services.AddDbContext<HRDataContext>(options =>
{
    options.UseSqlServer(config.ConnectionStrings.MTWorkHRConnectionString);
    //  options.UseSqlServer(builder.Configuration.GetSection("ConnectionStrings:MTWorkHRConnectionString").Value);
});




builder.Configuration.Bind(config);
builder.Services.AddApplicationServices(config);
builder.Services.AddInfrastructureIdentityServices(config);
//builder.Services.AddPersistenceServices(builder.Configuration);
//builder.Services.AddIdentityServices(config);
builder.Services.AddHostedService<DbMigrationService>();




if (builder.Environment.IsDevelopment())
{
    var mockBlobServiceClient = new Mock<BlobServiceClient>();

    // Mock BlobContainerClient since this is what BlobServiceClient interacts with.
    var mockBlobContainerClient = new Mock<BlobContainerClient>();

    // Set up the mock to return a mock BlobContainerClient when requested.
    mockBlobServiceClient
        .Setup(x => x.GetBlobContainerClient(It.IsAny<string>()))
        .Returns(mockBlobContainerClient.Object);

    builder.Services.AddSingleton(mockBlobServiceClient.Object);
}
else
{
    // Use the actual connection string for production or other environments.
    builder.Services.AddSingleton(x => new BlobServiceClient(config.ConnectionStrings.BlobConnectionString));
}

//builder.Services.AddControllers();
builder.Services.AddControllers(options =>
{
    //add filter by instance
    options.Filters.Add(new InputValidationActionFilter());
    //add filter By the type
    options.Filters.Add(typeof(InputValidationActionFilter));
});
//disable default model validation, because we handle this in InputValidationActionFilter and LoggingMiddleware.
builder.Services.Configure<ApiBehaviorOptions>(options =>
{
    options.SuppressModelStateInvalidFilter = true;
});

builder.Services.AddDevExpressControls(); // Add DevExpress Reporting controls
builder.Services.AddSingleton<MatchMoveService>();
//Reporting






builder.Services.AddScoped<ReportStorageWebExtension, CustomReportStorageWebExtension>();

builder.Services.ConfigureReportingServices(configurator => {
    configurator.ConfigureWebDocumentViewer(viewerConfigurator => {
        viewerConfigurator.UseCachedReportSourceBuilder();
    });
});

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
//builder.Services.AddSwaggerGen();
//--------------------------
builder.Services.AddSignalR(options =>
{
    options.EnableDetailedErrors = true;
});
builder.Services.AddCors(options => {
    options.AddPolicy("CORSPolicy", builder => builder.AllowAnyMethod().AllowAnyHeader().AllowCredentials().SetIsOriginAllowed((hosts) => true));
});
builder.Services.AddSwaggerGen(swagger =>
{
    //This is to apply global headers for all requests
    swagger.OperationFilter<HeaderOperationFilter>();

    //This is to export enums to front
    swagger.SchemaFilter<EnumSchemaFilter>();

    //This is to generate the Default UI of Swagger Documentation
    swagger.SwaggerDoc("v1", new OpenApiInfo
    {
        Version = "v1",
        Title = "MTWorkHR.API",
        Description = "MTWorkHR.APIDesc"
    });

    swagger.CustomOperationIds(
            d => (d.ActionDescriptor as ControllerActionDescriptor)?.ControllerName + (d.ActionDescriptor as ControllerActionDescriptor)?.ActionName
        );

    // To Enable authorization using Swagger (JWT)
    swagger.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
    {
        Name = "Authorization",
        Type = SecuritySchemeType.ApiKey,
        Scheme = "Bearer",
        BearerFormat = "JWT",
        In = ParameterLocation.Header,
        Description = "Enter 'Bearer' [space] and then your valid token in the text input below.\r\n\r\nExample: \"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\"",
    });
    swagger.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                          new OpenApiSecurityScheme
                            {
                                Reference = new OpenApiReference
                                {
                                    Type = ReferenceType.SecurityScheme,
                                    Id = "Bearer"
                                }
                            },
                            new string[] {}

                    }
                });
});

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("SuperAdminOnly", policy => policy.RequireRole("Admin"));
});

//--------------------------
var app = builder.Build();

// Configure the HTTP request pipeline.
// if (app.Environment.IsDevelopment())
// {
app.UseDevExpressControls(); // Required for DevExpress Reporting


app.UseExceptionHandler(errorApp =>
{
    errorApp.Run(async context =>
    {
        var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
        if (exceptionHandlerPathFeature?.Error is FaultException faultException)
        {
            var logger = context.RequestServices.GetRequiredService<ILogger<Program>>();
            logger.LogError("DevExpress Report Error: {Message}", faultException.Message);
        }

        context.Response.StatusCode = 500;
        await context.Response.WriteAsync("An error occurred while generating the report.");
    });
});


app.UseSwagger();
//app.UseSwaggerUI();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "MTWorkHR.API v1"));
// }


app.UseRouting();  // <-- Add UseRouting() here
app.UseMiddleware<LoggingMiddleware>();

//app.UseCors(x => x
//    .WithOrigins("https://api.mtwork.com", "https://mtworkhrclient.azurewebsites.net", "http://localhost:4200", "https://www.mtwork.com") // Allowed origins without trailing slash
//    .AllowAnyMethod()
//    .AllowAnyHeader()
//    .AllowCredentials() // Allows credentials
//);
app.UseCors("CORSPolicy");



app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
    endpoints.MapHub<ChatHub>("/chatHub"); // Map your SignalR hub
});
app.MapControllers();
//app.MapHub<ChatHub>("/chatHub");

app.Run();
