using CashLineERP.Contracts.Procurement;

namespace CashLineERP.Application.Procurement;

public sealed class PurchaseRequisitionService : IPurchaseRequisitionService
{
    private readonly IPurchaseRequisitionRepository _purchaseRequisitionRepository;

    public PurchaseRequisitionService(IPurchaseRequisitionRepository purchaseRequisitionRepository)
    {
        _purchaseRequisitionRepository = purchaseRequisitionRepository;
    }

    public IReadOnlyCollection<PurchaseRequisitionResponse> GetPurchaseRequisitions()
    {
        return _purchaseRequisitionRepository.GetPurchaseRequisitions()
            .Select(Map)
            .ToArray();
    }

    public PurchaseRequisitionResponse? GetPurchaseRequisition(long requisitionId)
    {
        var requisition = _purchaseRequisitionRepository.GetPurchaseRequisition(requisitionId);
        return requisition is null ? null : Map(requisition);
    }

    public PurchaseRequisitionResponse CreatePurchaseRequisition(CreatePurchaseRequisitionRequest request)
    {
        var requisition = _purchaseRequisitionRepository.Create(new CreatePurchaseRequisitionCommand(
            request.BranchId,
            request.RequesterUserId,
            request.RequisitionDate,
            request.NeedByDate,
            request.PurposeText,
            request.CurrencyCode,
            request.Lines.Select(line => new CreatePurchaseRequisitionLineCommand(
                line.ItemId,
                line.RequestedQuantity,
                line.UnitOfMeasureCode,
                line.NeedByDate,
                line.EstimatedUnitPrice,
                line.Notes)).ToArray()));

        return Map(requisition);
    }

    public PurchaseRequisitionResponse SubmitPurchaseRequisition(long requisitionId, long actorUserId)
    {
        return Map(_purchaseRequisitionRepository.Submit(requisitionId, actorUserId));
    }

    private static PurchaseRequisitionResponse Map(PurchaseRequisitionDetailView requisition) =>
        new(
            requisition.PurchaseRequisitionId,
            requisition.RequisitionNumber,
            requisition.BranchId,
            requisition.RequesterUserId,
            requisition.RequisitionDate,
            requisition.NeedByDate,
            requisition.StatusCode,
            requisition.PurposeText,
            requisition.CurrencyCode,
            requisition.EstimatedTotalAmount,
            requisition.Lines.Select(line => new PurchaseRequisitionLineResponse(
                line.LineId,
                line.LineNumber,
                line.ItemId,
                line.RequestedQuantity,
                line.UnitOfMeasureCode,
                line.NeedByDate,
                line.EstimatedUnitPrice,
                line.StatusCode,
                line.Notes)).ToArray());
}
