using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Nalu.Web.Models;
using Nalu.Web.Services;

namespace Nalu.Web.Endpoints;

public static class PlaygroundEndpoints
{
    private const int DailyLimit = 10;

    public static void MapPlaygroundEndpoints(this WebApplication app)
    {
        // Extraction validators — ExtractionRequest body
        app.MapPost("/v1/playground/extract/{validator}", async (
            string validator,
            HttpContext ctx,
            [FromBody] ExtractionRequest req,
            ExtractionPipeline pipeline,
            IMemoryCache cache,
            CancellationToken ct) =>
        {
            if (!CheckRateLimit(ctx, cache, out var remaining))
                return Results.Json(new { error = "Limite diário de 10 chamadas atingido. Crie uma conta para 3.000 créditos grátis." }, statusCode: 429);

            ctx.Response.Headers["X-Playground-Calls-Remaining"] = remaining.ToString();

            try
            {
                var result = await pipeline.ExecuteAsync($"validate_{validator.Replace("-", "_")}", req, ct);
                return Results.Ok(result);
            }
            catch (Exception ex)
            {
                return Results.Json(new { error = ex.Message }, statusCode: 503);
            }
        })
        .AllowAnonymous()
        .WithTags("Playground")
        .WithSummary("Playground — sem auth, 10 chamadas/IP/dia");

        // validate_reply — ReplyRequest body (different schema)
        app.MapPost("/v1/playground/extract/reply", async (
            HttpContext ctx,
            [FromBody] ReplyRequest req,
            ReplyService replyService,
            IMemoryCache cache,
            CancellationToken ct) =>
        {
            if (!CheckRateLimit(ctx, cache, out var remaining))
                return Results.Json(new { error = "Limite diário de 10 chamadas atingido. Crie uma conta para 3.000 créditos grátis." }, statusCode: 429);

            ctx.Response.Headers["X-Playground-Calls-Remaining"] = remaining.ToString();

            try
            {
                var result = await replyService.AnalyzeAsync(req, ct);
                return Results.Ok(result);
            }
            catch (Exception ex)
            {
                return Results.Json(new { error = ex.Message }, statusCode: 503);
            }
        })
        .AllowAnonymous()
        .WithTags("Playground")
        .WithSummary("Playground validate_reply — sem auth, 10 chamadas/IP/dia");
    }

    private static bool CheckRateLimit(HttpContext ctx, IMemoryCache cache, out int remaining)
    {
        var ip = ctx.Connection.RemoteIpAddress?.ToString() ?? "unknown";
        var cacheKey = $"pg:{ip}:{DateTime.UtcNow:yyyyMMdd}";

        var count = cache.GetOrCreate(cacheKey, e =>
        {
            e.AbsoluteExpiration = DateTime.UtcNow.Date.AddDays(1);
            return 0;
        });

        if (count >= DailyLimit)
        {
            remaining = 0;
            return false;
        }

        cache.Set(cacheKey, count + 1, new MemoryCacheEntryOptions
        {
            AbsoluteExpiration = DateTime.UtcNow.Date.AddDays(1)
        });

        remaining = DailyLimit - count - 1;
        return true;
    }
}
