using CashLineERP.Application.Procurement;
using Microsoft.EntityFrameworkCore;
using CashLineERP.Domain.Procurement;
using CashLineERP.SharedKernel.Workflow;

namespace CashLineERP.Infrastructure.Persistence.Repositories;

public sealed class PurchaseOrderRepository : IPurchaseOrderRepository
{
    private readonly CashLineErpDbContext _dbContext;

    public PurchaseOrderRepository(CashLineErpDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public IReadOnlyCollection<PurchaseOrderDetailView> GetPurchaseOrders()
    {
        return _dbContext.PurchaseOrders
            .AsNoTracking()
            .Include(purchaseOrder => purchaseOrder.Lines)
            .OrderByDescending(purchaseOrder => purchaseOrder.PurchaseOrderDate)
            .ThenByDescending(purchaseOrder => purchaseOrder.Id)
            .ToArray()
            .Select(Map)
            .ToArray();
    }

    public PurchaseOrderDetailView? GetPurchaseOrder(long purchaseOrderId)
    {
        var purchaseOrder = _dbContext.PurchaseOrders
            .AsNoTracking()
            .Include(existingPurchaseOrder => existingPurchaseOrder.Lines)
            .SingleOrDefault(existingPurchaseOrder => existingPurchaseOrder.Id == purchaseOrderId);

        return purchaseOrder is null ? null : Map(purchaseOrder);
    }

    private static PurchaseOrderDetailView Map(PurchaseOrder purchaseOrder) =>
        new(
            purchaseOrder.Id,
            purchaseOrder.PurchaseOrderNumber,
            purchaseOrder.BranchId,
            purchaseOrder.SupplierId,
            purchaseOrder.PurchaseRequisitionId,
            purchaseOrder.PurchaseOrderDate,
            purchaseOrder.CurrencyCode,
            purchaseOrder.ExchangeRate,
            WorkflowStatusSeedIds.ToCode(purchaseOrder.StatusId),
            purchaseOrder.SubtotalAmount,
            purchaseOrder.TaxAmount,
            purchaseOrder.TotalAmount,
            purchaseOrder.Lines.OrderBy(line => line.LineNumber).Select(line => new PurchaseOrderLineView(
                line.Id,
                line.LineNumber,
                line.ItemId,
                line.WarehouseId,
                line.OrderedQuantity,
                line.ReceivedQuantity,
                line.UnitOfMeasureCode,
                line.UnitPrice,
                line.TaxCode,
                line.LineNetAmount,
                line.LineTaxAmount,
                line.LineTotalAmount)).ToArray());
}
