using FastEndpoints;
using KArtSell.BuildingBlocks.Time;
using KArtSell.Host.Jobs;
using KArtSell.Modules.ModelOperations.ShadowRun;
using Microsoft.Extensions.Logging;

namespace KArtSell.Host.Features.ShadowRun;

/// <summary>
/// POST /api/shadow-runs
/// Initiate a 252+ trading-day model validation run.
/// Returns 202 Accepted with job tracking info.
/// </summary>
public class InitiateShadowRunEndpoint : Endpoint<InitiateShadowRunRequest, InitiateShadowRunResponse>
{
    private InitiateShadowRunHandler? _handler;
    private ILogger<InitiateShadowRunEndpoint>? _logger;

    private static readonly Action<ILogger, Guid, Exception?> LogRequestReceived =
        LoggerMessage.Define<Guid>(
            LogLevel.Information,
            new EventId(1, nameof(LogRequestReceived)),
            "Shadow run request received: {ModelId}");

    private static readonly Action<ILogger, Exception?> LogRequestFailed =
        LoggerMessage.Define(
            LogLevel.Error,
            new EventId(2, nameof(LogRequestFailed)),
            "Shadow run initiation failed");

    public override void Configure()
    {
        Post("/shadow-runs");  // RoutePrefix "api" added automatically in Program.cs
        Roles("Admin", "Researcher");  // RBAC: Only Admin or Researcher can initiate
        Validator<InitiateShadowRunValidator>();
    }

    public override async Task HandleAsync(InitiateShadowRunRequest req, CancellationToken ct)
    {
        _handler = Resolve<InitiateShadowRunHandler>();
        _logger = Resolve<ILogger<InitiateShadowRunEndpoint>>();

        var correlationId = HttpContext.Items["CorrelationId"] as Guid? ?? Guid.NewGuid();

        try
        {
            LogRequestReceived(_logger, req.ModelId, null);

            var response = await _handler.HandleAsync(req, correlationId, ct);

            // 202 Accepted: Job queued, results available later via polling
            HttpContext.Response.StatusCode = 202;
            await HttpContext.Response.WriteAsJsonAsync(response, ct);
        }
        catch (InvalidOperationException ex)
        {
            ThrowError(ex.Message, 400);
        }
        catch (Exception ex)
        {
            LogRequestFailed(_logger, ex);
            ThrowError("Shadow run initiation failed. Please retry.", 500);
        }
    }
}

/// <summary>
/// POST /api/test/shadow-run-direct
/// Direct synchronous test execution (bypass Hangfire queue)
/// </summary>
[DontRegister]
public class TestDirectShadowRunEndpoint(IClock clock) : Endpoint<InitiateShadowRunRequest, object>
{
    private ILogger<TestDirectShadowRunEndpoint>? _logger;

    public override void Configure()
    {
        Post("/test/shadow-run-direct");
        AllowAnonymous();
    }

    public override async Task HandleAsync(InitiateShadowRunRequest req, CancellationToken ct)
    {
        _logger = Resolve<ILogger<TestDirectShadowRunEndpoint>>();

        var correlationId = Guid.NewGuid();

        try
        {
            _logger.LogInformation("🔥 Direct test execution started (bypass queue)");

            // Resolve ShadowRunJob and execute directly
            var job = Resolve<ShadowRunJob>();
            var command = new ShadowRunCommand(
                ModelId: req.ModelId,
                CorrelationId: correlationId,
                IdempotencyKey: Guid.NewGuid(),
                WindowStartDate: req.WindowStart,
                WindowEndDate: req.WindowEnd,
                PhaseFilter: MarketPhaseFilter.All);

            _logger.LogInformation("🚀 Executing ShadowRunJob directly (no queue)...");
            var startTime = clock.UtcNow;

            await job.ExecuteAsync(command, ct);

            var duration = clock.UtcNow - startTime;
            _logger.LogInformation("✅ Direct execution completed in {Duration}ms", duration.TotalMilliseconds);

            HttpContext.Response.StatusCode = 200;
            await HttpContext.Response.WriteAsJsonAsync(new
            {
                Success = true,
                RunId = command.RunId,
                CorrelationId = correlationId,
                DurationMs = duration.TotalMilliseconds,
                Message = "Shadow run executed successfully. Check database for persisted results."
            }, ct);
        }
        catch (Exception ex)
        {
            _logger?.LogError(ex, "❌ Direct test execution failed: {Message}", ex.Message);
            HttpContext.Response.StatusCode = 500;
            await HttpContext.Response.WriteAsJsonAsync(
                new { Success = false, Error = ex.Message, Stack = ex.StackTrace },
                ct);
        }
    }
}
