using QuantEngine.Web.Components;
using QuantEngine.Web.Services;
using QuantEngine.Infrastructure.Data;
using QuantEngine.Infrastructure.Repositories;
using QuantEngine.Infrastructure.Services;
using QuantEngine.Core.Interfaces;
using QuantEngine.Application.Services;
using System.Text.Json;
using static QuantEngine.Application.Services.DataCollectionService;
using Microsoft.FluentUI.AspNetCore.Components;
using Serilog;
using QuantEngine.Web.Infrastructure;
using QuantEngine.Web.Endpoints;

// Serilog Configuration with Telegram Sink
Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .WriteTo.Console()
    .WriteTo.Sink(new TelegramSink("8734507814:AAFyacLMai8GB4K-hQ_Nd3t3D01A-h1ZdV0", "-5460205872"))
    .CreateLogger();

var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog();

// Add services to the container.
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

// Fluent UI Services
builder.Services.AddFluentUIComponents();

// PostgreSQL Dapper Setup
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection")
    ?? "Host=127.0.0.1;Database=giteadb;Username=gitea;Password=C8RFlZ9fdQrBA1vyLhLDS4v70I8dJfRS2ERJW4+zsS4=;Search Path=quantengine;";
builder.Services.AddSingleton<IDbConnectionFactory>(new DbConnectionFactory(connectionString));
builder.Services.AddScoped<IWorkspaceRepository, WorkspaceRepository>();
builder.Services.AddScoped<IPostgresqlHistoryStore, PostgresqlHistoryStore>();
builder.Services.AddScoped<IPostgresqlHistorySnapshotReader, PostgresqlHistorySnapshotReader>();
builder.Services.AddScoped<HistoryIngestionService>();

// Collection Pipeline Services (PostgreSQL-backed implementations)
builder.Services.AddScoped<ICollectionRepository, CollectionRepository>();
builder.Services.AddScoped<ITokenCache, PostgresTokenCache>();
builder.Services.AddScoped<IKisApiClient, KisApiClient>();
builder.Services.AddScoped<DataCollectionService>();

// HTTP Client & API Services
builder.Services.AddHttpClient<ApiClient>();
builder.Services.AddScoped<ApiClient>();

var app = builder.Build();

// Initialize database tables (PostgreSQL-backed repositories)
using (var scope = app.Services.CreateScope())
{
    var tokenCache = scope.ServiceProvider.GetRequiredService<ITokenCache>();
    var collectionRepo = scope.ServiceProvider.GetRequiredService<ICollectionRepository>();

    try
    {
        // Ensure tables exist on startup
        await tokenCache.GetCachedTokenAsync("_init_test_");
        await collectionRepo.GetDashboardStateAsync();
        Log.Information("Database tables initialized successfully");
    }
    catch (Exception ex)
    {
        Log.Warning($"Database initialization warning: {ex.Message}");
    }
}

// Enable reverse proxy subpath mapping
app.UsePathBase("/quant");

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
    app.UseHsts();
}
// Redirect status code pages only for non-API routes
app.UseStatusCodePages(async ctx =>
{
    if (!ctx.HttpContext.Request.Path.StartsWithSegments("/api"))
        ctx.HttpContext.Response.Redirect("/not-found");
});

app.UseHttpsRedirection();

app.UseAntiforgery();

app.MapStaticAssets();

// Collection API Endpoints (must be before MapRazorComponents)
app.MapCollectionEndpoints();

app.MapGet("/api/history/{domain}", async (string domain, int? limit, IPostgresqlHistorySnapshotReader reader) =>
{
    var rows = await reader.ReadAsync(domain, limit ?? 500);
    return Results.Ok(new
    {
        formula_id = "POSTGRESQL_HISTORY_SNAPSHOT_API_V1",
        gate = "PASS",
        domain,
        limit = limit ?? 500,
        rows
    });
});

app.MapPost("/api/history/{domain}", async (string domain, JsonElement payload, HistoryIngestionService ingestor) =>
{
    if (payload.ValueKind != JsonValueKind.Object)
    {
        return Results.BadRequest(new { gate = "FAIL", error = "payload_must_be_object" });
    }

    var dict = JsonSerializer.Deserialize<Dictionary<string, object?>>(payload.GetRawText())
              ?? new Dictionary<string, object?>();
    var affected = domain switch
    {
        "decision_result_history" => await ingestor.AppendDecisionAsync(dict),
        "factor_output_history" => await ingestor.AppendFactorOutputAsync(dict),
        "market_raw_history" => await ingestor.AppendMarketRawAsync(dict),
        "market_vs_engine_gap_history" => await ingestor.AppendGapAsync(dict),
        _ => -1
    };
    if (affected < 0)
    {
        return Results.BadRequest(new { gate = "FAIL", error = "unsupported_domain" });
    }
    return Results.Ok(new
    {
        formula_id = "POSTGRESQL_HISTORY_APPEND_API_V1",
        gate = "PASS",
        domain,
        affected
    });
});

app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

app.Run();

