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

namespace Indotalent.Features.Sales.SalesReturnReport.Cqrs;

public record GetSalesReturnReportListDto
{
    public string? Id { get; init; }
    public string? SalesReturnNumber { get; init; }
    public string? DeliveryOrderNumber { 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? ReturnDate { get; init; }
}

public record GetSalesReturnReportListQuery() : IRequest<List<GetSalesReturnReportListDto>>;

public class GetSalesReturnReportListHandler : IRequestHandler<GetSalesReturnReportListQuery, List<GetSalesReturnReportListDto>>
{
    private readonly AppDbContext _context;

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

    public async Task<List<GetSalesReturnReportListDto>> Handle(GetSalesReturnReportListQuery request, CancellationToken cancellationToken)
    {
        var query = _context.InventoryTransaction
            .AsNoTracking()
            .Include(x => x.Product)
            .Include(x => x.Warehouse)
            .Where(x => x.ModuleName == "SalesReturn")
            .GroupJoin(
                _context.SalesReturn.AsNoTracking()
                    .Include(x => x.DeliveryOrder)
                        .ThenInclude(x => x!.SalesOrder)
                            .ThenInclude(x => x!.Customer),
                inventory => inventory.ModuleId,
                salesReturn => salesReturn.Id,
                (inventory, returns) => new { inventory, returns }
            )
            .SelectMany(
                x => x.returns.DefaultIfEmpty(),
                (x, salesReturn) => new GetSalesReturnReportListDto
                {
                    Id = x.inventory.Id,
                    SalesReturnNumber = salesReturn != null ? salesReturn.AutoNumber : x.inventory.ModuleNumber,
                    DeliveryOrderNumber = (salesReturn != null && salesReturn.DeliveryOrder != null) ? salesReturn.DeliveryOrder.AutoNumber : string.Empty,
                    CustomerName = (salesReturn != null && salesReturn.DeliveryOrder != null && salesReturn.DeliveryOrder.SalesOrder != null && salesReturn.DeliveryOrder.SalesOrder.Customer != null) ? salesReturn.DeliveryOrder.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,
                    ReturnDate = salesReturn != null ? salesReturn.ReturnDate : x.inventory.MovementDate
                }
            )
            .OrderByDescending(x => x.ReturnDate);

        return await query.ToListAsync(cancellationToken);
    }
}