using FastEndpoints;
using QuantEngine.Core.Interfaces;

namespace QuantEngine.Web.Endpoints;

public class GetCollectionStateEndpoint : EndpointWithoutRequest<CollectionDashboardStateRecord>
{
    private readonly ICollectionRepository _repo;

    public GetCollectionStateEndpoint(ICollectionRepository repo)
    {
        _repo = repo;
    }

    public override void Configure()
    {
        Get("/api/collection/state");
        AllowAnonymous();
        Description(d => d
            .Produces<CollectionDashboardStateRecord>(200)
            .Produces(500));
    }

    public override async Task HandleAsync(CancellationToken ct)
    {
        try
        {
            var state = await _repo.GetDashboardStateAsync();
            await SendOkAsync(state, ct);
        }
        catch
        {
            await SendErrorsAsync(500, ct);
        }
    }
}

public class GetRecentRunsRequest
{
    public int Limit { get; set; } = 20;
}

public class GetRecentRunsResponse
{
    public List<CollectionRunRecord> Runs { get; set; } = new();
    public int Count { get; set; }
}

public class GetRecentRunsEndpoint : Endpoint<GetRecentRunsRequest, GetRecentRunsResponse>
{
    private readonly ICollectionRepository _repo;

    public GetRecentRunsEndpoint(ICollectionRepository repo)
    {
        _repo = repo;
    }

    public override void Configure()
    {
        Get("/api/collection/runs");
        AllowAnonymous();
        Description(d => d
            .Produces<GetRecentRunsResponse>(200)
            .Produces(500));
    }

    public override async Task HandleAsync(GetRecentRunsRequest req, CancellationToken ct)
    {
        try
        {
            var runs = await _repo.GetRecentRunsAsync(req.Limit);
            await SendOkAsync(new GetRecentRunsResponse { Runs = runs, Count = runs.Count }, ct);
        }
        catch
        {
            await SendErrorsAsync(500, ct);
        }
    }
}

public class GetRunSnapshotsRequest
{
    public string RunId { get; set; } = "";
}

public class GetRunSnapshotsResponse
{
    public string RunId { get; set; } = "";
    public List<CollectionSnapshotRecord> Snapshots { get; set; } = new();
    public int Count { get; set; }
}

public class GetRunSnapshotsEndpoint : Endpoint<GetRunSnapshotsRequest, GetRunSnapshotsResponse>
{
    private readonly ICollectionRepository _repo;

    public GetRunSnapshotsEndpoint(ICollectionRepository repo)
    {
        _repo = repo;
    }

    public override void Configure()
    {
        Get("/api/collection/runs/{RunId}/snapshots");
        AllowAnonymous();
        Description(d => d
            .Produces<GetRunSnapshotsResponse>(200)
            .Produces(404)
            .Produces(500));
    }

    public override async Task HandleAsync(GetRunSnapshotsRequest req, CancellationToken ct)
    {
        try
        {
            var snapshots = await _repo.GetRunSnapshotsAsync(req.RunId);
            await SendOkAsync(new GetRunSnapshotsResponse { RunId = req.RunId, Snapshots = snapshots, Count = snapshots.Count }, ct);
        }
        catch
        {
            await SendErrorsAsync(500, ct);
        }
    }
}

public class GetRunErrorsRequest
{
    public string RunId { get; set; } = "";
    public int Limit { get; set; } = 50;
}

public class GetRunErrorsResponse
{
    public string RunId { get; set; } = "";
    public List<CollectionErrorRecord> Errors { get; set; } = new();
    public int Count { get; set; }
}

public class GetRunErrorsEndpoint : Endpoint<GetRunErrorsRequest, GetRunErrorsResponse>
{
    private readonly ICollectionRepository _repo;

    public GetRunErrorsEndpoint(ICollectionRepository repo)
    {
        _repo = repo;
    }

    public override void Configure()
    {
        Get("/api/collection/runs/{RunId}/errors");
        AllowAnonymous();
        Description(d => d
            .Produces<GetRunErrorsResponse>(200)
            .Produces(404)
            .Produces(500));
    }

    public override async Task HandleAsync(GetRunErrorsRequest req, CancellationToken ct)
    {
        try
        {
            var errors = await _repo.GetRunErrorsAsync(req.RunId, req.Limit);
            await SendOkAsync(new GetRunErrorsResponse { RunId = req.RunId, Errors = errors, Count = errors.Count }, ct);
        }
        catch
        {
            await SendErrorsAsync(500, ct);
        }
    }
}

public class GetLatestSnapshotsRequest
{
    public string Ticker { get; set; } = "";
    public int Limit { get; set; } = 10;
}

public class GetLatestSnapshotsResponse
{
    public string Ticker { get; set; } = "";
    public List<CollectionSnapshotRecord> Snapshots { get; set; } = new();
    public int Count { get; set; }
}

public class GetLatestSnapshotsEndpoint : Endpoint<GetLatestSnapshotsRequest, GetLatestSnapshotsResponse>
{
    private readonly ICollectionRepository _repo;

    public GetLatestSnapshotsEndpoint(ICollectionRepository repo)
    {
        _repo = repo;
    }

    public override void Configure()
    {
        Get("/api/collection/latest/{Ticker}");
        AllowAnonymous();
        Description(d => d
            .Produces<GetLatestSnapshotsResponse>(200)
            .Produces(500));
    }

    public override async Task HandleAsync(GetLatestSnapshotsRequest req, CancellationToken ct)
    {
        try
        {
            var snapshots = await _repo.GetLatestSnapshotsForTickerAsync(req.Ticker, req.Limit);
            await SendOkAsync(new GetLatestSnapshotsResponse { Ticker = req.Ticker, Snapshots = snapshots, Count = snapshots.Count }, ct);
        }
        catch
        {
            await SendErrorsAsync(500, ct);
        }
    }
}

public class StartCollectionRunEndpoint : EndpointWithoutRequest
{
    public override void Configure()
    {
        Post("/api/collection/run");
        AllowAnonymous();
        Description(d => d
            .Produces(202)
            .Produces(500));
    }

    public override async Task HandleAsync(CancellationToken ct)
    {
        // Return 202 Accepted status code via generic status code handler
        await SendResultAsync(Microsoft.AspNetCore.Http.Results.Accepted());
    }
}
