using CashLineERP.Contracts.Inventory;

namespace CashLineERP.Application.Inventory;

public sealed class WarehouseTransferService : IWarehouseTransferService
{
    private readonly IWarehouseTransferRepository _repository;

    public WarehouseTransferService(IWarehouseTransferRepository repository)
    {
        _repository = repository;
    }

    public IReadOnlyCollection<WarehouseTransferResponse> GetWarehouseTransfers() =>
        _repository.GetWarehouseTransfers().Select(Map).ToArray();

    public WarehouseTransferResponse? GetWarehouseTransfer(long warehouseTransferId)
    {
        var transfer = _repository.GetWarehouseTransfer(warehouseTransferId);
        return transfer is null ? null : Map(transfer);
    }

    public WarehouseTransferResponse CreateWarehouseTransfer(CreateWarehouseTransferRequest request)
    {
        var transfer = _repository.Create(new CreateWarehouseTransferCommand(
            request.BranchId,
            request.FromWarehouseId,
            request.ToWarehouseId,
            request.TransferDate,
            request.ReasonCode,
            request.Notes,
            request.Lines.Select(line => new CreateWarehouseTransferLineCommand(
                line.ItemId,
                line.FromWarehouseLocationId,
                line.ToWarehouseLocationId,
                line.QuantityTransferred,
                line.UnitOfMeasureCode,
                line.UnitCost,
                line.StockStatus,
                line.BatchNumber,
                line.SerialNumber,
                line.Notes)).ToArray()));

        return Map(transfer);
    }

    public WarehouseTransferResponse SubmitWarehouseTransfer(long warehouseTransferId, long actorUserId) =>
        Map(_repository.Submit(warehouseTransferId, actorUserId));

    public WarehouseTransferResponse ApproveWarehouseTransfer(long warehouseTransferId, long actorUserId) =>
        Map(_repository.Approve(warehouseTransferId, actorUserId));

    public WarehouseTransferResponse PostWarehouseTransfer(long warehouseTransferId, long actorUserId) =>
        Map(_repository.Post(warehouseTransferId, actorUserId));

    private static WarehouseTransferResponse Map(WarehouseTransferDetailView transfer) =>
        new(
            transfer.WarehouseTransferId,
            transfer.TransferNumber,
            transfer.BranchId,
            transfer.FromWarehouseId,
            transfer.ToWarehouseId,
            transfer.TransferDate,
            transfer.ReasonCode,
            transfer.Notes,
            transfer.StatusCode,
            transfer.TotalTransferQuantity,
            transfer.SubmittedAtUtc,
            transfer.SubmittedByUserId,
            transfer.ApprovedAtUtc,
            transfer.ApprovedByUserId,
            transfer.PostedAtUtc,
            transfer.PostedByUserId,
            transfer.Lines.Select(line => new WarehouseTransferLineResponse(
                line.WarehouseTransferLineId,
                line.LineNumber,
                line.ItemId,
                line.FromWarehouseLocationId,
                line.ToWarehouseLocationId,
                line.QuantityTransferred,
                line.UnitOfMeasureCode,
                line.UnitCost,
                line.StockStatus,
                line.BatchNumber,
                line.SerialNumber,
                line.Notes)).ToArray());
}
