package de.effigenix.application.inventory;

import de.effigenix.domain.inventory.InventoryAction;
import de.effigenix.domain.inventory.StorageLocation;
import de.effigenix.domain.inventory.StorageLocationError;
import de.effigenix.domain.inventory.StorageLocationId;
import de.effigenix.domain.inventory.StorageLocationRepository;
import de.effigenix.shared.common.Result;
import de.effigenix.shared.security.ActorId;
import de.effigenix.shared.security.AuthorizationPort;

public class GetStorageLocation {

    private final StorageLocationRepository storageLocationRepository;
    private final AuthorizationPort authPort;

    public GetStorageLocation(StorageLocationRepository storageLocationRepository, AuthorizationPort authPort) {
        this.storageLocationRepository = storageLocationRepository;
        this.authPort = authPort;
    }

    public Result<StorageLocationError, StorageLocation> execute(String storageLocationId, ActorId performedBy) {
        if (!authPort.can(performedBy, InventoryAction.STOCK_READ)) {
            return Result.failure(new StorageLocationError.Unauthorized("Not authorized to view storage location"));
        }

        if (storageLocationId == null || storageLocationId.isBlank()) {
            return Result.failure(new StorageLocationError.StorageLocationNotFound(storageLocationId));
        }

        return switch (storageLocationRepository.findById(StorageLocationId.of(storageLocationId))) {
            case Result.Failure(var err) -> Result.failure(new StorageLocationError.RepositoryFailure(err.message()));
            case Result.Success(var opt) -> opt
                    .<Result<StorageLocationError, StorageLocation>>map(Result::success)
                    .orElseGet(() -> Result.failure(new StorageLocationError.StorageLocationNotFound(storageLocationId)));
        };
    }
}
