using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Hosting;
using Meezi.API.Extensions;
using Meezi.Infrastructure.Data;
using Serilog;

namespace Meezi.API;

public partial class Program
{
    public static async Task Main(string[] args)
    {
        Log.Logger = new LoggerConfiguration()
            .WriteTo.Console()
            .CreateLogger();

        var hostAborted = false;
        try
        {
            var app = BuildWebApplication(args);

            if (app.Configuration.GetValue<bool>("RUN_MIGRATIONS"))
            {
                await using var scope = app.Services.CreateAsyncScope();
                var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
                await db.Database.MigrateAsync();
                await DatabaseSchemaPatches.ApplyAsync(db);
            }

            await PlatformDataSeeder.EnsureCatalogUpgradesAsync(app.Services);

            if (!app.Configuration.GetValue<bool>("Testing:SkipSeed"))
            {
                await DevelopmentDataSeeder.SeedAsync(app.Services);
                await PlatformDataSeeder.SeedAsync(app.Services);
            }

            await app.RunAsync();
        }
        catch (HostAbortedException)
        {
            hostAborted = true;
            throw;
        }
        catch (Exception ex)
        {
            Log.Fatal(ex, "Application terminated unexpectedly");
        }
        finally
        {
            if (!hostAborted)
                await Log.CloseAndFlushAsync();
        }
    }

    public static WebApplication BuildWebApplication(
        string[] args,
        Action<WebApplicationBuilder>? configureBeforeServices = null,
        Action<WebApplicationBuilder>? configureAfterServices = null)
    {
        var builder = WebApplication.CreateBuilder(args);
        configureBeforeServices?.Invoke(builder);

        builder.Host.UseSerilog((context, services, configuration) => configuration
            .ReadFrom.Configuration(context.Configuration)
            .ReadFrom.Services(services)
            .Enrich.FromLogContext()
            .WriteTo.Console());

        builder.Services.AddMeeziServices(builder.Configuration);
        configureAfterServices?.Invoke(builder);

        var app = builder.Build();
        app.ConfigureMeeziPipeline();
        return app;
    }
}
