package de.effigenix.application.inventory;

import de.effigenix.domain.inventory.*;
import de.effigenix.shared.common.RepositoryError;
import de.effigenix.shared.common.Result;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Transactional(readOnly = true)
public class ListStorageLocations {

    private final StorageLocationRepository storageLocationRepository;

    public ListStorageLocations(StorageLocationRepository storageLocationRepository) {
        this.storageLocationRepository = storageLocationRepository;
    }

    public Result<StorageLocationError, List<StorageLocation>> execute(String storageType, Boolean active) {
        if (storageType != null) {
            return findByStorageType(storageType, active);
        }
        if (active == null) {
            return mapResult(storageLocationRepository.findAll());
        }
        var result = mapResult(storageLocationRepository.findAll());
        if (result.isSuccess()) {
            return Result.success(result.unsafeGetValue().stream()
                    .filter(loc -> loc.active() == active)
                    .toList());
        }
        return result;
    }

    private Result<StorageLocationError, List<StorageLocation>> findByStorageType(String storageType, Boolean active) {
        StorageType type;
        try {
            type = StorageType.valueOf(storageType);
        } catch (IllegalArgumentException e) {
            return Result.failure(new StorageLocationError.InvalidStorageType(storageType));
        }

        var result = mapResult(storageLocationRepository.findByStorageType(type));
        if (result.isSuccess() && active != null) {
            return Result.success(result.unsafeGetValue().stream()
                    .filter(loc -> loc.active() == active)
                    .toList());
        }
        return result;
    }

    private Result<StorageLocationError, List<StorageLocation>> mapResult(
            Result<RepositoryError, List<StorageLocation>> result) {
        return switch (result) {
            case Result.Failure(var err) -> Result.failure(new StorageLocationError.RepositoryFailure(err.message()));
            case Result.Success(var locations) -> Result.success(locations);
        };
    }
}
