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

namespace Indotalent.Features.Purchase.DebitNote.Cqrs;

public record GetPurchaseReturnDetailForDebitNoteQuery(string PurchaseReturnId) : IRequest<GetDebitNoteByIdResponse?>;

public class GetPurchaseReturnDetailForDebitNoteHandler : IRequestHandler<GetPurchaseReturnDetailForDebitNoteQuery, GetDebitNoteByIdResponse?>
{
    private readonly AppDbContext _context;
    public GetPurchaseReturnDetailForDebitNoteHandler(AppDbContext context) => _context = context;

    public async Task<GetDebitNoteByIdResponse?> Handle(GetPurchaseReturnDetailForDebitNoteQuery request, CancellationToken cancellationToken)
    {
        var purchaseReturn = await _context.PurchaseReturn
            .AsNoTracking()
            .Include(x => x.GoodsReceive)
                .ThenInclude(gr => gr!.PurchaseOrder)
                    .ThenInclude(po => po!.Tax)
            .FirstOrDefaultAsync(x => x.Id == request.PurchaseReturnId, cancellationToken);

        if (purchaseReturn == null) return null;

        var purchaseOrder = purchaseReturn.GoodsReceive?.PurchaseOrder;
        var taxRate = purchaseOrder?.Tax?.PercentageValue ?? 0;

        var transactions = await _context.InventoryTransaction
            .AsNoTracking()
            .Include(x => x.Product)
            .Where(x => x.ModuleId == request.PurchaseReturnId && x.ModuleName == nameof(Data.Entities.PurchaseReturn))
            .ToListAsync(cancellationToken);

        var items = new List<DebitNoteItemResponse>();
        decimal subTotal = 0;

        foreach (var trans in transactions)
        {
            var poItem = await _context.PurchaseOrderItem
                .AsNoTracking()
                .FirstOrDefaultAsync(x => x.PurchaseOrderId == purchaseOrder!.Id && x.ProductId == trans.ProductId, cancellationToken);

            var unitPrice = poItem?.UnitPrice ?? 0;
            var qty = Math.Abs(trans.Movement ?? 0);
            var total = unitPrice * (decimal)qty;

            items.Add(new DebitNoteItemResponse
            {
                Id = trans.Id,
                ProductId = trans.ProductId,
                ProductName = trans.Product?.Name,
                UnitPrice = unitPrice,
                Quantity = qty,
                Total = total
            });

            subTotal += total;
        }

        var taxAmount = subTotal * (decimal)(taxRate / 100);

        return new GetDebitNoteByIdResponse
        {
            PurchaseReturnId = purchaseReturn.Id,
            PurchaseReturnNumber = purchaseReturn.AutoNumber,
            BeforeTaxAmount = subTotal,
            TaxAmount = taxAmount,
            AfterTaxAmount = subTotal + taxAmount,
            Items = items
        };
    }
}