package de.effigenix.application.inventory;

import de.effigenix.domain.inventory.InventoryAction;
import de.effigenix.domain.inventory.InventoryCount;
import de.effigenix.domain.inventory.InventoryCountError;
import de.effigenix.domain.inventory.InventoryCountId;
import de.effigenix.domain.inventory.InventoryCountRepository;
import de.effigenix.shared.common.Result;
import de.effigenix.shared.security.ActorId;
import de.effigenix.shared.security.AuthorizationPort;

public class GetInventoryCount {

    private final InventoryCountRepository inventoryCountRepository;
    private final AuthorizationPort authPort;

    public GetInventoryCount(InventoryCountRepository inventoryCountRepository, AuthorizationPort authPort) {
        this.inventoryCountRepository = inventoryCountRepository;
        this.authPort = authPort;
    }

    public Result<InventoryCountError, InventoryCount> execute(String inventoryCountId, ActorId actorId) {
        if (!authPort.can(actorId, InventoryAction.INVENTORY_COUNT_READ)) {
            return Result.failure(new InventoryCountError.Unauthorized("Not authorized to view inventory counts"));
        }

        if (inventoryCountId == null || inventoryCountId.isBlank()) {
            return Result.failure(new InventoryCountError.InvalidInventoryCountId("must not be blank"));
        }

        return switch (inventoryCountRepository.findById(InventoryCountId.of(inventoryCountId))) {
            case Result.Failure(var err) -> Result.failure(new InventoryCountError.RepositoryFailure(err.message()));
            case Result.Success(var opt) -> opt
                    .<Result<InventoryCountError, InventoryCount>>map(Result::success)
                    .orElseGet(() -> Result.failure(new InventoryCountError.InventoryCountNotFound(inventoryCountId)));
        };
    }
}
