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

namespace Indotalent.Features.Purchase.PurchaseReturnReport.Cqrs;

public record GetPurchaseReturnReportListDto
{
    public string? Id { get; init; }
    public string? PurchaseReturnNumber { get; init; }
    public string? GoodsReceiveNumber { get; init; }
    public string? VendorName { 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 GetPurchaseReturnReportListQuery() : IRequest<List<GetPurchaseReturnReportListDto>>;

public class GetPurchaseReturnReportListHandler : IRequestHandler<GetPurchaseReturnReportListQuery, List<GetPurchaseReturnReportListDto>>
{
    private readonly AppDbContext _context;

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

    public async Task<List<GetPurchaseReturnReportListDto>> Handle(GetPurchaseReturnReportListQuery request, CancellationToken cancellationToken)
    {
        var query = _context.InventoryTransaction
            .AsNoTracking()
            .Include(x => x.Product)
            .Include(x => x.Warehouse)
            .Where(x => x.ModuleName == "PurchaseReturn")
            .GroupJoin(
                _context.PurchaseReturn.AsNoTracking()
                    .Include(x => x.GoodsReceive)
                        .ThenInclude(x => x!.PurchaseOrder)
                            .ThenInclude(x => x!.Vendor),
                inventory => inventory.ModuleId,
                purchaseReturn => purchaseReturn.Id,
                (inventory, returns) => new { inventory, returns }
            )
            .SelectMany(
                x => x.returns.DefaultIfEmpty(),
                (x, purchaseReturn) => new GetPurchaseReturnReportListDto
                {
                    Id = x.inventory.Id,
                    PurchaseReturnNumber = purchaseReturn != null ? purchaseReturn.AutoNumber : x.inventory.ModuleNumber,
                    GoodsReceiveNumber = (purchaseReturn != null && purchaseReturn.GoodsReceive != null) ? purchaseReturn.GoodsReceive.AutoNumber : string.Empty,
                    VendorName = (purchaseReturn != null && purchaseReturn.GoodsReceive != null && purchaseReturn.GoodsReceive.PurchaseOrder != null && purchaseReturn.GoodsReceive.PurchaseOrder.Vendor != null) ? purchaseReturn.GoodsReceive.PurchaseOrder.Vendor.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 = purchaseReturn != null ? purchaseReturn.ReturnDate : x.inventory.MovementDate
                }
            )
            .OrderByDescending(x => x.ReturnDate);

        return await query.ToListAsync(cancellationToken);
    }
}