using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Vegasco.Server.Api.Cars; using Vegasco.Server.Api.Persistence; namespace Vegasco.Server.Api.Consumptions; public static class GetConsumptions { public class ApiResponse { public IEnumerable Consumptions { get; set; } = []; } public record ResponseDto( Guid Id, DateTimeOffset DateTime, double Distance, double Amount, CarDto Car, double? LiterPer100Km); public record CarDto( Guid Id, string Name) { public static CarDto FromCar(Car car) { return new CarDto(car.Id.Value, car.Name); } } public class Request { [FromQuery(Name = "page")] public int? Page { get; set; } [FromQuery(Name = "pageSize")] public int? PageSize { get; set; } } public static RouteHandlerBuilder MapEndpoint(IEndpointRouteBuilder builder) { return builder .MapGet("consumptions", Endpoint) .WithDescription("Returns all consumption entries") .WithTags("Consumptions") .Produces(); } private static async Task> Endpoint( [AsParameters] Request request, ApplicationDbContext dbContext, CancellationToken cancellationToken) { Dictionary> consumptionsByCar = await dbContext.Consumptions .OrderByDescending(x => x.DateTime) .Include(x => x.Car) .GroupBy(x => x.CarId) .ToDictionaryAsync(x => x.Key, x => x.ToList(), cancellationToken); List responses = []; foreach (var consumptions in consumptionsByCar.Select(x => x.Value)) { for (int i = 0; i < consumptions.Count; i++) { Consumption consumption = consumptions[i]; double? literPer100Km = null; bool isLast = i == consumptions.Count - 1; if (!isLast) { Consumption previousConsumption = consumptions[i + 1]; double distanceDiff = consumption.Distance - previousConsumption.Distance; literPer100Km = consumption.Amount / (distanceDiff / 100); } responses.Add(new ResponseDto( consumption.Id.Value, consumption.DateTime, consumption.Distance, consumption.Amount, CarDto.FromCar(consumption.Car), literPer100Km)); } } ApiResponse apiResponse = new() { Consumptions = responses }; return TypedResults.Ok(apiResponse); } }