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

namespace Indotalent.Features.Inventory.TransactionReport.Cqrs;

public record GetInventoryTransactionReportListDto
{
    public string? Id { get; init; }
    public string? ModuleId { get; init; }
    public string? ModuleName { get; init; }
    public string? ModuleCode { get; init; }
    public string? ModuleNumber { get; init; }
    public DateTime? MovementDate { get; init; }
    public string? StatusName { get; init; }
    public string? AutoNumber { get; init; }
    public string? WarehouseName { get; init; }
    public string? ProductName { get; init; }
    public double? Movement { get; init; }
    public string? TransTypeName { get; init; }
    public double? Stock { get; init; }
    public string? WarehouseFromName { get; init; }
    public string? WarehouseToName { get; init; }
    public DateTimeOffset? CreatedAt { get; init; }
}

public record GetInventoryTransactionReportListQuery() : IRequest<List<GetInventoryTransactionReportListDto>>;

public class GetInventoryTransactionReportListHandler : IRequestHandler<GetInventoryTransactionReportListQuery, List<GetInventoryTransactionReportListDto>>
{
    private readonly AppDbContext _context;

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

    public async Task<List<GetInventoryTransactionReportListDto>> Handle(GetInventoryTransactionReportListQuery request, CancellationToken cancellationToken)
    {
        var query = _context.InventoryTransaction
            .AsNoTracking()
            .Include(x => x.Warehouse)
            .Include(x => x.Product)
            .Include(x => x.WarehouseFrom)
            .Include(x => x.WarehouseTo)
            .Where(x =>
                x.Product!.Physical == true &&
                x.Warehouse!.SystemWarehouse == false &&
                x.Status == Data.Enums.InventoryTransactionStatus.Confirmed
            )
            .OrderByDescending(x => x.CreatedAt);

        var results = await query.Select(x => new GetInventoryTransactionReportListDto
        {
            Id = x.Id,
            ModuleId = x.ModuleId,
            ModuleName = x.ModuleName,
            ModuleCode = x.ModuleCode,
            ModuleNumber = x.ModuleNumber,
            MovementDate = x.MovementDate,
            StatusName = x.Status.GetDescription(),
            AutoNumber = x.AutoNumber,
            WarehouseName = x.Warehouse != null ? x.Warehouse.Name : string.Empty,
            ProductName = x.Product != null ? x.Product.AutoNumber + " " + x.Product.Name : string.Empty,
            Movement = x.Movement,
            TransTypeName = x.TransType.HasValue ? x.TransType.Value.GetDescription() : string.Empty,
            Stock = x.Stock,
            WarehouseFromName = x.WarehouseFrom != null ? x.WarehouseFrom.Name : string.Empty,
            WarehouseToName = x.WarehouseTo != null ? x.WarehouseTo.Name : string.Empty,
            CreatedAt = x.CreatedAt
        }).ToListAsync(cancellationToken);

        return results;
    }
}