using Indotalent.Infrastructure.Database;
using MediatR;
using Microsoft.EntityFrameworkCore;

namespace Indotalent.Features.Sales.DeliveryReport.Cqrs;

public record GetDeliveryReportListDto
{
    public string? Id { get; init; }
    public string? DeliveryOrderNumber { get; init; }
    public string? SalesOrderNumber { get; init; }
    public string? CustomerName { get; init; }
    public string? WarehouseName { get; init; }
    public string? ProductNumber { get; init; }
    public string? ProductName { get; init; }
    public double? Quantity { get; init; }
    public DateTime? DeliveryDate { get; init; }
}

public record GetDeliveryReportListQuery() : IRequest<List<GetDeliveryReportListDto>>;

public class GetDeliveryReportListHandler : IRequestHandler<GetDeliveryReportListQuery, List<GetDeliveryReportListDto>>
{
    private readonly AppDbContext _context;

    public GetDeliveryReportListHandler(AppDbContext context)
    {
        _context = context;
    }

    public async Task<List<GetDeliveryReportListDto>> Handle(GetDeliveryReportListQuery request, CancellationToken cancellationToken)
    {
        var query = _context.InventoryTransaction
            .AsNoTracking()
            .Include(x => x.Product)
            .Include(x => x.Warehouse)
            .Where(x => x.ModuleName == "DeliveryOrder")
            .GroupJoin(
                _context.DeliveryOrder.AsNoTracking()
                    .Include(x => x.SalesOrder)
                    .ThenInclude(x => x!.Customer),
                inventory => inventory.ModuleId,
                delivery => delivery.Id,
                (inventory, deliveries) => new { inventory, deliveries }
            )
            .SelectMany(
                x => x.deliveries.DefaultIfEmpty(),
                (x, delivery) => new GetDeliveryReportListDto
                {
                    Id = x.inventory.Id,
                    DeliveryOrderNumber = delivery != null ? delivery.AutoNumber : x.inventory.ModuleNumber,
                    SalesOrderNumber = (delivery != null && delivery.SalesOrder != null) ? delivery.SalesOrder.AutoNumber : string.Empty,
                    CustomerName = (delivery != null && delivery.SalesOrder != null && delivery.SalesOrder.Customer != null) ? delivery.SalesOrder.Customer.Name : string.Empty,
                    WarehouseName = x.inventory.Warehouse != null ? x.inventory.Warehouse.Name : string.Empty,
                    ProductNumber = x.inventory.Product != null ? x.inventory.Product.AutoNumber : string.Empty,
                    ProductName = x.inventory.Product != null ? x.inventory.Product.Name : string.Empty,
                    Quantity = x.inventory.Movement,
                    DeliveryDate = delivery != null ? delivery.DeliveryDate : x.inventory.MovementDate
                }
            )
            .OrderByDescending(x => x.DeliveryDate);

        return await query.ToListAsync(cancellationToken);
    }
}