package de.effigenix.domain.production;

import de.effigenix.shared.common.Result;

import java.util.List;

public class BatchTraceabilityService {

    static final int DEFAULT_MAX_DEPTH = 10;

    private final BatchRepository batchRepository;

    public BatchTraceabilityService(BatchRepository batchRepository) {
        this.batchRepository = batchRepository;
    }

    public Result<BatchError, List<TracedBatch>> traceForward(BatchId startBatchId) {
        return traceForward(startBatchId, DEFAULT_MAX_DEPTH);
    }

    public Result<BatchError, List<TracedBatch>> traceForward(BatchId startBatchId, int maxDepth) {
        switch (batchRepository.findById(startBatchId)) {
            case Result.Failure(var err) ->
                { return Result.failure(new BatchError.RepositoryFailure(err.message())); }
            case Result.Success(var opt) -> {
                if (opt.isEmpty()) {
                    return Result.failure(new BatchError.BatchNotFound(startBatchId));
                }
            }
        }

        if (maxDepth <= 0) {
            return Result.success(List.of());
        }

        return switch (batchRepository.traceForward(startBatchId, maxDepth)) {
            case Result.Failure(var err) ->
                Result.failure(new BatchError.RepositoryFailure(err.message()));
            case Result.Success(var traced) ->
                Result.success(traced);
        };
    }

    public Result<BatchError, List<TracedBatch>> traceBackward(BatchId startBatchId) {
        return traceBackward(startBatchId, DEFAULT_MAX_DEPTH);
    }

    public Result<BatchError, List<TracedBatch>> traceBackward(BatchId startBatchId, int maxDepth) {
        switch (batchRepository.findById(startBatchId)) {
            case Result.Failure(var err) ->
                { return Result.failure(new BatchError.RepositoryFailure(err.message())); }
            case Result.Success(var opt) -> {
                if (opt.isEmpty()) {
                    return Result.failure(new BatchError.BatchNotFound(startBatchId));
                }
            }
        }

        if (maxDepth <= 0) {
            return Result.success(List.of());
        }

        return switch (batchRepository.traceBackward(startBatchId, maxDepth)) {
            case Result.Failure(var err) ->
                Result.failure(new BatchError.RepositoryFailure(err.message()));
            case Result.Success(var traced) ->
                Result.success(traced);
        };
    }
}
