package de.effigenix.domain.production;

import java.util.List;

public sealed interface RecipeError {

    String code();
    String message();

    record RecipeNotFound(RecipeId id) implements RecipeError {
        @Override public String code() { return "RECIPE_NOT_FOUND"; }
        @Override public String message() { return "Recipe with ID '" + id.value() + "' not found"; }
    }

    record NameAndVersionAlreadyExists(String name, int version) implements RecipeError {
        @Override public String code() { return "RECIPE_NAME_VERSION_EXISTS"; }
        @Override public String message() { return "Recipe '" + name + "' version " + version + " already exists"; }
    }

    record InvalidShelfLife(String reason) implements RecipeError {
        @Override public String code() { return "RECIPE_INVALID_SHELF_LIFE"; }
        @Override public String message() { return "Invalid shelf life: " + reason; }
    }

    record ValidationFailure(String message) implements RecipeError {
        @Override public String code() { return "RECIPE_VALIDATION_ERROR"; }
    }

    record NotInDraftStatus() implements RecipeError {
        @Override public String code() { return "RECIPE_NOT_IN_DRAFT"; }
        @Override public String message() { return "Recipe can only be modified in DRAFT status"; }
    }

    record DuplicatePosition(int position) implements RecipeError {
        @Override public String code() { return "RECIPE_DUPLICATE_POSITION"; }
        @Override public String message() { return "Ingredient position " + position + " is already taken"; }
    }

    record IngredientNotFound(IngredientId id) implements RecipeError {
        @Override public String code() { return "RECIPE_INGREDIENT_NOT_FOUND"; }
        @Override public String message() { return "Ingredient with ID '" + id.value() + "' not found"; }
    }

    record DuplicateStepNumber(int stepNumber) implements RecipeError {
        @Override public String code() { return "RECIPE_DUPLICATE_STEP_NUMBER"; }
        @Override public String message() { return "Step number " + stepNumber + " is already taken"; }
    }

    record StepNotFound(int stepNumber) implements RecipeError {
        @Override public String code() { return "RECIPE_STEP_NOT_FOUND"; }
        @Override public String message() { return "Production step with number " + stepNumber + " not found"; }
    }

    record NoIngredients() implements RecipeError {
        @Override public String code() { return "RECIPE_NO_INGREDIENTS"; }
        @Override public String message() { return "Recipe must have at least one ingredient to be activated"; }
    }

    record InvalidStatusTransition(RecipeStatus current, RecipeStatus target) implements RecipeError {
        @Override public String code() { return "RECIPE_INVALID_STATUS_TRANSITION"; }
        @Override public String message() { return "Cannot transition from " + current + " to " + target; }
    }

    record Unauthorized(String message) implements RecipeError {
        @Override public String code() { return "UNAUTHORIZED"; }
    }

    record CyclicDependencyDetected(List<String> cyclePath) implements RecipeError {
        @Override public String code() { return "RECIPE_CYCLIC_DEPENDENCY"; }
        @Override public String message() { return "Cyclic dependency detected: " + String.join(" → ", cyclePath); }
    }

    record RepositoryFailure(String message) implements RecipeError {
        @Override public String code() { return "REPOSITORY_ERROR"; }
    }
}
