using GerbilManagerWebAPI.Common;
using GerbilManagerWebAPI.Dtos;
using GerbilManagerWebAPI.Models;
using Gridify;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.EntityFrameworkCore;

namespace GerbilManagerWebAPI.Endpoints
{
    public static class ColorVarietyEndpoints
    {
        public static IEndpointRouteBuilder MapColorVarietyEndpoints(this IEndpointRouteBuilder app)
        {
            var group = app.MapGroup("/color-varieties").WithTags("ColorVarieties");

            group.MapGet("/", async ([AsParameters] GridifyParams query, ApplicationContext db) =>
                TypedResults.Ok(await db.ColorVarieties.AsNoTracking().OrderBy(v => v.SortOrder)
                    .ToPagedResultAsync(query, ToDto)));

            group.MapGet("/{id:guid}", async Task<Results<Ok<ColorVarietyDto>, NotFound>> (Guid id, ApplicationContext db) =>
            {
                var v = await db.ColorVarieties.AsNoTracking().FirstOrDefaultAsync(x => x.Id == id);
                return v is null ? TypedResults.NotFound() : TypedResults.Ok(ToDto(v));
            });

            group.MapPost("/", async (ColorVarietyInput input, ApplicationContext db) =>
            {
                var v = new ColorVariety
                {
                    Id = Guid.NewGuid(),
                    Name = input.Name,
                    CanonicalGenotype = input.CanonicalGenotype,
                    SortOrder = input.SortOrder ?? 1000,
                };
                db.ColorVarieties.Add(v);
                await db.SaveChangesAsync();
                return TypedResults.Created($"/color-varieties/{v.Id}", ToDto(v));
            });

            group.MapPut("/{id:guid}", async Task<Results<NoContent, NotFound>> (Guid id, ColorVarietyInput input, ApplicationContext db) =>
            {
                var v = await db.ColorVarieties.FirstOrDefaultAsync(x => x.Id == id);
                if (v is null) return TypedResults.NotFound();
                v.Name = input.Name;
                v.CanonicalGenotype = input.CanonicalGenotype;
                if (input.SortOrder is int so) v.SortOrder = so;
                await db.SaveChangesAsync();
                return TypedResults.NoContent();
            });

            group.MapDelete("/{id:guid}", async Task<Results<NoContent, NotFound, Conflict<string>>> (Guid id, ApplicationContext db) =>
            {
                var v = await db.ColorVarieties.FirstOrDefaultAsync(x => x.Id == id);
                if (v is null) return TypedResults.NotFound();
                bool inUse = await db.Gerbils.AnyAsync(g => g.ColorVarietyId == id);
                if (inUse) return TypedResults.Conflict("Color variety is in use by one or more gerbils and cannot be deleted.");
                db.ColorVarieties.Remove(v);
                await db.SaveChangesAsync();
                return TypedResults.NoContent();
            });

            return app;
        }

        private static ColorVarietyDto ToDto(ColorVariety v) => new(v.Id, v.Name, v.CanonicalGenotype, v.SortOrder);
    }
}
