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

namespace GerbilManagerWebAPI.Endpoints
{
    /// <summary>
    /// RÜCKNAHMEN (RPRO3 getback_tb): zurückgekommene/zurückgenommene Tiere.
    ///   GET    /returns[?gerbilId=]  -> Liste, neueste zuerst (optional nach Tier gefiltert).
    ///   POST   /returns              -> Rücknahme erfassen, 201.
    ///   PUT    /returns/{id}         -> Rücknahme aktualisieren, 200.
    ///   DELETE /returns/{id}         -> Rücknahme löschen, 204.
    /// Entkoppelt von Gerbils/Contacts (lose nullable Guid-Spalten, kein FK), daher
    /// überleben Zeilen den Import-Re-Ingest-Wipe — wie Feedback.
    /// </summary>
    public static class ReturnRecordEndpoints
    {
        public static IEndpointRouteBuilder MapReturnRecordEndpoints(this IEndpointRouteBuilder app)
        {
            var group = app.MapGroup("/returns").WithTags("Returns");

            group.MapGet("/", async (ApplicationContext db, Guid? gerbilId) =>
            {
                var query = db.ReturnRecords.AsNoTracking();
                if (gerbilId is { } gid)
                    query = query.Where(r => r.GerbilId == gid);
                // In-Memory sortieren: SQLite (Test-Host) kann nicht nach DateTimeOffset ORDER BY-en.
                var rows = await query.ToListAsync();
                return TypedResults.Ok(rows
                    .OrderByDescending(r => r.ReturnDate ?? DateTime.MinValue)
                    .ThenByDescending(r => r.CreatedAt)
                    .Select(ToDto)
                    .ToList());
            });

            group.MapPost("/", async Task<Results<Created<ReturnRecordDto>, BadRequest<string>>> (
                ReturnRecordInput input, ApplicationContext db) =>
            {
                if (input.GerbilId is null && string.IsNullOrWhiteSpace(input.GerbilName))
                    return TypedResults.BadRequest("Es muss ein Tier (GerbilId oder GerbilName) angegeben werden.");

                var entity = new ReturnRecord
                {
                    Id = Guid.NewGuid(),
                    GerbilId = input.GerbilId,
                    GerbilName = Trimmed(input.GerbilName),
                    ReturnDate = input.ReturnDate,
                    ReturnPrice = input.ReturnPrice,
                    OriginalPrice = input.OriginalPrice,
                    OriginalSaleDate = input.OriginalSaleDate,
                    FromContactId = input.FromContactId,
                    FromContactName = Trimmed(input.FromContactName),
                    Note = Trimmed(input.Note),
                    CreatedAt = DateTimeOffset.UtcNow,
                };
                db.ReturnRecords.Add(entity);
                await db.SaveChangesAsync();
                return TypedResults.Created($"/returns/{entity.Id}", ToDto(entity));
            });

            group.MapPut("/{id:guid}", async Task<Results<Ok<ReturnRecordDto>, NotFound, BadRequest<string>>> (
                Guid id, ReturnRecordInput input, ApplicationContext db) =>
            {
                var entity = await db.ReturnRecords.FirstOrDefaultAsync(r => r.Id == id);
                if (entity is null) return TypedResults.NotFound();

                if (input.GerbilId is null && string.IsNullOrWhiteSpace(input.GerbilName))
                    return TypedResults.BadRequest("Es muss ein Tier (GerbilId oder GerbilName) angegeben werden.");

                entity.GerbilId = input.GerbilId;
                entity.GerbilName = Trimmed(input.GerbilName);
                entity.ReturnDate = input.ReturnDate;
                entity.ReturnPrice = input.ReturnPrice;
                entity.OriginalPrice = input.OriginalPrice;
                entity.OriginalSaleDate = input.OriginalSaleDate;
                entity.FromContactId = input.FromContactId;
                entity.FromContactName = Trimmed(input.FromContactName);
                entity.Note = Trimmed(input.Note);
                await db.SaveChangesAsync();
                return TypedResults.Ok(ToDto(entity));
            });

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

            return app;
        }

        private static string? Trimmed(string? s) =>
            string.IsNullOrWhiteSpace(s) ? null : s.Trim();

        private static ReturnRecordDto ToDto(ReturnRecord r) =>
            new(r.Id, r.GerbilId, r.GerbilName, r.ReturnDate, r.ReturnPrice, r.OriginalPrice,
                r.OriginalSaleDate, r.FromContactId, r.FromContactName, r.Note, r.CreatedAt);
    }
}
