package de.effigenix.application.inventory;

import de.effigenix.domain.inventory.InventoryAction;
import de.effigenix.domain.inventory.StockMovement;
import de.effigenix.domain.inventory.StockMovementError;
import de.effigenix.domain.inventory.StockMovementId;
import de.effigenix.domain.inventory.StockMovementRepository;
import de.effigenix.shared.common.Result;
import de.effigenix.shared.security.ActorId;
import de.effigenix.shared.security.AuthorizationPort;

public class GetStockMovement {

    private final StockMovementRepository stockMovementRepository;
    private final AuthorizationPort authPort;

    public GetStockMovement(StockMovementRepository stockMovementRepository, AuthorizationPort authPort) {
        this.stockMovementRepository = stockMovementRepository;
        this.authPort = authPort;
    }

    public Result<StockMovementError, StockMovement> execute(String stockMovementId, ActorId performedBy) {
        if (!authPort.can(performedBy, InventoryAction.STOCK_MOVEMENT_READ)) {
            return Result.failure(new StockMovementError.Unauthorized("Not authorized to view stock movements"));
        }

        if (stockMovementId == null || stockMovementId.isBlank()) {
            return Result.failure(new StockMovementError.StockMovementNotFound(stockMovementId));
        }

        return switch (stockMovementRepository.findById(StockMovementId.of(stockMovementId))) {
            case Result.Failure(var err) -> Result.failure(new StockMovementError.RepositoryFailure(err.message()));
            case Result.Success(var opt) -> opt
                    .<Result<StockMovementError, StockMovement>>map(Result::success)
                    .orElseGet(() -> Result.failure(new StockMovementError.StockMovementNotFound(stockMovementId)));
        };
    }
}
