using ASTRAIN.Api.Data;
using ASTRAIN.Api.Services;
using ASTRAIN.Shared.Dtos;
using ASTRAIN.Shared.Models;
using ASTRAIN.Shared.Requests;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;

namespace ASTRAIN.Api.Endpoints;

/// <summary>
/// Provides routine run-related endpoints.
/// </summary>
internal static class RoutineRunEndpoints
{
    /// <summary>
    /// Registers routine run routes under the provided route group.
    /// </summary>
    /// <param name="group">The API route group.</param>
    /// <returns>The same route group for chaining.</returns>
    public static RouteGroupBuilder MapRoutineRunEndpoints(this RouteGroupBuilder group)
    {
        group.MapGet("/users/{userId}/routines/{routineId:int}/last-run", async (string userId, int routineId, AppDbContext db, IConfiguration config) =>
            {
                var populateSampleData = config.GetValue("SampleData:Enabled", false);
                var user = await UserProvisioning.EnsureUserAsync(db, userId, populateSampleData);
                var lastRun = await db.RoutineRuns
                    .Include(rr => rr.Entries)
                    .Where(rr => rr.UserId == user.Id && rr.RoutineId == routineId)
                    .OrderByDescending(rr => rr.PerformedAt)
                    .FirstOrDefaultAsync();

                if (lastRun is null)
                {
                    return Results.Ok(new RoutineRunSummaryDto(DateTime.MinValue, new List<RoutineRunEntryDto>()));
                }

                var summary = new RoutineRunSummaryDto(
                    lastRun.PerformedAt,
                    lastRun.Entries
                        .Select(e => new RoutineRunEntryDto(e.ExerciseId, e.Weight, e.Completed))
                        .ToList());

                return Results.Ok(summary);
            })
            .WithSummary("Get last routine run")
            .WithDescription("Returns the most recent run summary for a routine.");

        group.MapPost("/users/{userId}/routines/{routineId:int}/runs", async (string userId, int routineId, RoutineRunRequest request, AppDbContext db, IConfiguration config) =>
            {
                var populateSampleData = config.GetValue("SampleData:Enabled", false);
                var user = await UserProvisioning.EnsureUserAsync(db, userId, populateSampleData);
                var routine = await db.Routines.FirstOrDefaultAsync(r => r.Id == routineId && r.UserId == user.Id);
                if (routine is null)
                {
                    return Results.NotFound();
                }

                var run = new RoutineRun
                {
                    RoutineId = routine.Id,
                    UserId = user.Id,
                    PerformedAt = DateTime.UtcNow,
                    Entries = request.Entries.Select(entry => new RoutineRunEntry
                    {
                        ExerciseId = entry.ExerciseId,
                        Weight = entry.Weight,
                        Completed = entry.Completed
                    }).ToList()
                };

                db.RoutineRuns.Add(run);
                await db.SaveChangesAsync();

                return Results.Ok(new { run.Id, run.PerformedAt });
            })
            .WithSummary("Create routine run")
            .WithDescription("Records a routine run with exercise entries.");

        return group;
    }
}
