using CashLineERP.Contracts.Procurement;

namespace CashLineERP.Application.Procurement;

public sealed class PurchaseReturnService : IPurchaseReturnService
{
    private readonly IPurchaseReturnRepository _repository;

    public PurchaseReturnService(IPurchaseReturnRepository repository)
    {
        _repository = repository;
    }

    public IReadOnlyCollection<PurchaseReturnResponse> GetPurchaseReturns() =>
        _repository.GetPurchaseReturns().Select(Map).ToArray();

    public PurchaseReturnResponse? GetPurchaseReturn(long purchaseReturnId)
    {
        var purchaseReturn = _repository.GetPurchaseReturn(purchaseReturnId);
        return purchaseReturn is null ? null : Map(purchaseReturn);
    }

    public PurchaseReturnResponse CreatePurchaseReturn(CreatePurchaseReturnRequest request)
    {
        var purchaseReturn = _repository.Create(new CreatePurchaseReturnCommand(
            request.BranchId,
            request.SupplierId,
            request.PurchaseOrderId,
            request.GoodsReceiptId,
            request.ReturnDate,
            request.ReturnWarehouseId,
            request.ReasonCode,
            request.Notes,
            request.Lines.Select(line => new CreatePurchaseReturnLineCommand(
                line.GoodsReceiptLineId,
                line.PurchaseOrderLineId,
                line.ItemId,
                line.QuantityReturned,
                line.WarehouseLocationId,
                line.BatchNumber,
                line.SerialNumber,
                line.Notes)).ToArray()));

        return Map(purchaseReturn);
    }

    public PurchaseReturnResponse SubmitPurchaseReturn(long purchaseReturnId, long actorUserId) =>
        Map(_repository.Submit(purchaseReturnId, actorUserId));

    public PurchaseReturnResponse PostPurchaseReturn(long purchaseReturnId, long actorUserId) =>
        Map(_repository.Post(purchaseReturnId, actorUserId));

    public PurchaseReturnResponse IssueDebitNote(long purchaseReturnId, IssuePurchaseReturnDebitNoteRequest request) =>
        Map(_repository.IssueDebitNote(purchaseReturnId, request));

    private static PurchaseReturnResponse Map(PurchaseReturnDetailView purchaseReturn) =>
        new(
            purchaseReturn.PurchaseReturnId,
            purchaseReturn.PurchaseReturnNumber,
            purchaseReturn.BranchId,
            purchaseReturn.SupplierId,
            purchaseReturn.PurchaseOrderId,
            purchaseReturn.GoodsReceiptId,
            purchaseReturn.ReturnDate,
            purchaseReturn.ReturnWarehouseId,
            purchaseReturn.ReasonCode,
            purchaseReturn.Notes,
            purchaseReturn.StatusCode,
            purchaseReturn.TotalReturnedQuantity,
            purchaseReturn.DebitNoteBillId,
            purchaseReturn.DebitNoteIssuedAtUtc,
            purchaseReturn.Lines.Select(line => new PurchaseReturnLineResponse(
                line.PurchaseReturnLineId,
                line.LineNumber,
                line.GoodsReceiptLineId,
                line.PurchaseOrderLineId,
                line.ItemId,
                line.QuantityReturned,
                line.WarehouseLocationId,
                line.BatchNumber,
                line.SerialNumber,
                line.Notes)).ToArray());
}
