using Microsoft.EntityFrameworkCore;
using RolemasterDb.App.Components;
using RolemasterDb.App.Data;
using RolemasterDb.App.Frontend.AppState;
using RolemasterDb.App.Features;

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseStaticWebAssets();
var connectionString = builder.Configuration.GetConnectionString("RolemasterDb") ?? "Data Source=rolemaster.db";

builder.Services.AddRazorComponents().AddInteractiveServerComponents();
builder.Services.AddDbContextFactory<RolemasterDbContext>(options => options.UseSqlite(connectionString));
builder.Services.AddSingleton<CriticalImportArtifactLocator>();
builder.Services.AddScoped<LookupService>();
builder.Services.AddScoped<BrowserStorageService>();
builder.Services.AddScoped<PinnedTablesState>();
builder.Services.AddScoped<RecentTablesState>();
builder.Services.AddScoped<ShellOmniboxState>();
builder.Services.AddScoped<TableContextState>();
builder.Services.AddSingleton<TableContextUrlSerializer>();
builder.Services.AddScoped<ThemeState>();

var app = builder.Build();
await RolemasterDbInitializer.InitializeAsync(app.Services);

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
}

app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true);
app.UseAntiforgery();

app.MapStaticAssets();
var api = app.MapGroup("/api");
api.MapGet("/reference-data", async (LookupService lookupService, CancellationToken cancellationToken) => Results.Ok(await lookupService.GetReferenceDataAsync(cancellationToken)));
api.MapPost("/lookup/attack", async (AttackLookupRequest request, LookupService lookupService, CancellationToken cancellationToken) =>
{
    var result = await lookupService.LookupAttackAsync(request, cancellationToken);
    return result is null ? Results.NotFound() : Results.Ok(result);
});
api.MapPost("/lookup/critical", async (CriticalLookupRequest request, LookupService lookupService, CancellationToken cancellationToken) =>
{
    var result = await lookupService.LookupCriticalAsync(request, cancellationToken);
    return result is null ? Results.NotFound() : Results.Ok(result);
});
api.MapGet("/tables/critical/{slug}/cells/{resultId:int}", async (string slug, int resultId, LookupService lookupService, CancellationToken cancellationToken) =>
{
    var result = await lookupService.GetCriticalCellEditorAsync(slug, resultId, cancellationToken);
    return result is null ? Results.NotFound() : Results.Ok(result);
});
api.MapGet("/tables/critical/{slug}/cells/{resultId:int}/source-image", async (string slug, int resultId, LookupService lookupService, HttpContext httpContext, CancellationToken cancellationToken) =>
{
    var filePath = await lookupService.GetCriticalSourceImagePathAsync(slug, resultId, cancellationToken);
    if (filePath is null)
    {
        return Results.NotFound();
    }

    httpContext.Response.Headers.CacheControl = "no-store, no-cache, max-age=0";
    httpContext.Response.Headers.Pragma = "no-cache";
    httpContext.Response.Headers.Expires = "0";
    return Results.File(filePath, "image/png");
});
api.MapPost("/tables/critical/{slug}/cells/{resultId:int}/reparse", async (string slug, int resultId, CriticalCellReparseRequest request, LookupService lookupService, CancellationToken cancellationToken) =>
{
    var result = await lookupService.ReparseCriticalCellAsync(slug, resultId, request.CurrentState, cancellationToken);
    return result is null ? Results.NotFound() : Results.Ok(result);
});
api.MapPut("/tables/critical/{slug}/cells/{resultId:int}", async (string slug, int resultId, CriticalCellUpdateRequest request, LookupService lookupService, CancellationToken cancellationToken) =>
{
    var result = await lookupService.UpdateCriticalCellAsync(slug, resultId, request, cancellationToken);
    return result is null ? Results.NotFound() : Results.Ok(result);
});
app.MapRazorComponents<App>().AddInteractiveServerRenderMode();

app.Run();