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

namespace GerbilManagerWebAPI.Endpoints
{
    /// <summary>
    /// ERWERB: acquisition data per animal (purchase date/price/note).
    ///   GET    /acquisitions?gerbilId=…  -> records for one animal (or all), newest date first.
    ///   GET    /acquisitions/{id}        -> a single record.
    ///   POST   /acquisitions             -> create, returns 201.
    ///   PUT    /acquisitions/{id}        -> update, returns 204.
    ///   DELETE /acquisitions/{id}        -> delete, returns 204.
    /// Decoupled from gerbils/contacts (loose nullable Guid columns, no FK), so rows survive
    /// the import re-ingest wipe (mirrors Feedback).
    /// </summary>
    public static class AcquisitionEndpoints
    {
        public static IEndpointRouteBuilder MapAcquisitionEndpoints(this IEndpointRouteBuilder app)
        {
            var group = app.MapGroup("/acquisitions").WithTags("Acquisitions");

            group.MapGet("/", async (ApplicationContext db, Guid? gerbilId) =>
            {
                var rows = await db.AcquisitionRecords.AsNoTracking()
                    .Where(a => gerbilId == null || a.GerbilId == gerbilId)
                    .ToListAsync();
                // Order in memory: SQLite (test host) cannot ORDER BY a DateTimeOffset column,
                // and DateOnly ordering stays consistent across providers this way.
                return TypedResults.Ok(rows
                    .OrderByDescending(a => a.Date ?? DateOnly.MinValue)
                    .ThenByDescending(a => a.CreatedAt)
                    .Select(ToDto)
                    .ToList());
            });

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

            group.MapPost("/", async (AcquisitionInput input, ApplicationContext db) =>
            {
                var a = new AcquisitionRecord
                {
                    Id = Guid.NewGuid(),
                    GerbilId = input.GerbilId,
                    SourceContactId = input.SourceContactId,
                    Date = input.Date,
                    Price = input.Price,
                    Note = string.IsNullOrWhiteSpace(input.Note) ? null : input.Note.Trim(),
                    CreatedAt = DateTimeOffset.UtcNow,
                };
                db.AcquisitionRecords.Add(a);
                await db.SaveChangesAsync();
                return TypedResults.Created($"/acquisitions/{a.Id}", ToDto(a));
            });

            group.MapPut("/{id:guid}", async Task<Results<NoContent, NotFound>> (Guid id, AcquisitionInput input, ApplicationContext db) =>
            {
                var a = await db.AcquisitionRecords.FirstOrDefaultAsync(x => x.Id == id);
                if (a is null) return TypedResults.NotFound();
                a.GerbilId = input.GerbilId;
                a.SourceContactId = input.SourceContactId;
                a.Date = input.Date;
                a.Price = input.Price;
                a.Note = string.IsNullOrWhiteSpace(input.Note) ? null : input.Note.Trim();
                await db.SaveChangesAsync();
                return TypedResults.NoContent();
            });

            group.MapDelete("/{id:guid}", async Task<Results<NoContent, NotFound>> (Guid id, ApplicationContext db) =>
            {
                var a = await db.AcquisitionRecords.FirstOrDefaultAsync(x => x.Id == id);
                if (a is null) return TypedResults.NotFound();
                db.AcquisitionRecords.Remove(a);
                await db.SaveChangesAsync();
                return TypedResults.NoContent();
            });

            return app;
        }

        private static AcquisitionDto ToDto(AcquisitionRecord a) =>
            new(a.Id, a.GerbilId, a.SourceContactId, a.Date, a.Price, a.Note, a.CreatedAt);
    }
}
