using Apollinare.API.Hubs;
using Apollinare.API.Services;
using Apollinare.API.Services.Reports;
using Apollinare.API.Modules.Warehouse.Services;
using Apollinare.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
using System.Text.Json.Serialization;

var builder = WebApplication.CreateBuilder(args);

// Database
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection")
    ?? "Data Source=apollinare.db";
builder.Services.AddDbContext<AppollinareDbContext>(options =>
    options.UseSqlite(connectionString));

// Services
builder.Services.AddScoped<EventoCostiService>();
builder.Services.AddScoped<DemoDataService>();
builder.Services.AddScoped<ReportGeneratorService>();
builder.Services.AddScoped<ModuleService>();
builder.Services.AddScoped<AutoCodeService>();
builder.Services.AddSingleton<DataNotificationService>();

// Warehouse Module Services
builder.Services.AddScoped<IWarehouseService, WarehouseService>();

// Memory cache for module state
builder.Services.AddMemoryCache();

// SignalR - with increased message size for template sync (default is 32KB)
builder.Services.AddSignalR(options =>
    {
        options.MaximumReceiveMessageSize = 1024 * 1024; // 1MB max message size
    })
    .AddJsonProtocol(options =>
    {
        options.PayloadSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
        options.PayloadSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
    });

// CORS - Allow credentials for SignalR (accepts any origin for external access)
builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowFrontend", policy =>
    {
        policy.SetIsOriginAllowed(_ => true) // Permette qualsiasi origine
              .AllowAnyHeader()
              .AllowAnyMethod()
              .AllowCredentials();
    });
});

// Controllers with JSON options
builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
        options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
    });

builder.Services.AddOpenApi();

var app = builder.Build();

// Apply pending migrations automatically on startup
using (var scope = app.Services.CreateScope())
{
    var db = scope.ServiceProvider.GetRequiredService<AppollinareDbContext>();
    var logger = scope.ServiceProvider.GetRequiredService<ILogger<Program>>();

    try
    {
        var pendingMigrations = await db.Database.GetPendingMigrationsAsync();
        if (pendingMigrations.Any())
        {
            logger.LogInformation("Applying {Count} pending migrations: {Migrations}",
                pendingMigrations.Count(),
                string.Join(", ", pendingMigrations));
            await db.Database.MigrateAsync();
            logger.LogInformation("Migrations applied successfully");
        }
        else
        {
            logger.LogInformation("Database is up to date, no migrations to apply");
        }
    }
    catch (Exception ex)
    {
        logger.LogError(ex, "Error applying migrations");
        throw;
    }

    // Seed data (only in development or if database is empty)
    DbSeeder.Seed(db);

    // Seed default modules
    var moduleService = scope.ServiceProvider.GetRequiredService<ModuleService>();
    await moduleService.SeedDefaultModulesAsync();

    // Seed warehouse default data
    var warehouseService = scope.ServiceProvider.GetRequiredService<IWarehouseService>();
    await warehouseService.SeedDefaultDataAsync();

    // Seed AutoCode configurations
    var autoCodeService = scope.ServiceProvider.GetRequiredService<AutoCodeService>();
    await autoCodeService.SeedDefaultConfigurationsAsync();
}

if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

app.UseCors("AllowFrontend");
app.UseWebSockets();
app.UseAuthorization();
app.MapControllers();
app.MapHub<DataHub>("/hubs/data");
app.MapHub<CollaborationHub>("/hubs/collaboration");

app.Run();
