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

namespace Indotalent.Features.Purchase.ReceiveReport.Cqrs;

public record GetReceiveReportListDto
{
    public string? Id { get; init; }
    public string? GoodsReceiveNumber { get; init; }
    public string? PurchaseOrderNumber { 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? ReceiveDate { get; init; }
}

public record GetReceiveReportListQuery() : IRequest<List<GetReceiveReportListDto>>;

public class GetReceiveReportListHandler : IRequestHandler<GetReceiveReportListQuery, List<GetReceiveReportListDto>>
{
    private readonly AppDbContext _context;

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

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

        return await query.ToListAsync(cancellationToken);
    }
}