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

namespace Indotalent.Features.Inventory.StockReport.Cqrs;

public record GetInventoryStockReportListDto
{
    public string? StatusName { get; init; }
    public string? WarehouseId { get; set; }
    public string? WarehouseName { get; init; }
    public string? ProductId { get; set; }
    public string? ProductName { get; init; }
    public string? ProductNumber { get; init; }
    public double? Stock { get; init; }
    public DateTimeOffset? CreatedAt { get; init; }
}

public record GetInventoryStockReportListQuery() : IRequest<List<GetInventoryStockReportListDto>>;

public class GetInventoryStockReportListHandler : IRequestHandler<GetInventoryStockReportListQuery, List<GetInventoryStockReportListDto>>
{
    private readonly AppDbContext _context;

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

    public async Task<List<GetInventoryStockReportListDto>> Handle(GetInventoryStockReportListQuery request, CancellationToken cancellationToken)
    {
        var results = await _context.InventoryTransaction
            .AsNoTracking()
            .Include(x => x.Warehouse)
            .Include(x => x.Product)
            .Where(x =>
                x.Product!.Physical == true &&
                x.Warehouse!.SystemWarehouse == false &&
                x.Status == Data.Enums.InventoryTransactionStatus.Confirmed
            )
            .GroupBy(x => new { x.WarehouseId, x.ProductId })
            .Select(group => new GetInventoryStockReportListDto
            {
                WarehouseId = group.Key.WarehouseId,
                ProductId = group.Key.ProductId,
                WarehouseName = group.Max(x => x.Warehouse!.Name),
                ProductName = group.Max(x => x.Product!.Name),
                ProductNumber = group.Max(x => x.Product!.AutoNumber),
                Stock = group.Sum(x => x.Stock),
                StatusName = group.Max(x => x.Status.ToString()),
                CreatedAt = group.Max(x => x.CreatedAt)
            })
            .OrderBy(x => x.WarehouseName)
            .ThenBy(x => x.ProductName)
            .ToListAsync(cancellationToken);

        return results;
    }
}