package de.effigenix.domain.production;

import de.effigenix.shared.common.Result;

/**
 * Child entity of Recipe representing a single production step.
 *
 * Invariants:
 * 1. StepNumber must be >= 1
 * 2. Description must not be blank
 * 3. DurationMinutes must be > 0 if set
 * 4. TemperatureCelsius must be between -273 and 1000 if set
 */
public class ProductionStep {

    private final ProductionStepId id;
    private final int stepNumber;
    private final String description;
    private final Integer durationMinutes;
    private final Integer temperatureCelsius;

    private ProductionStep(ProductionStepId id, int stepNumber, String description,
                           Integer durationMinutes, Integer temperatureCelsius) {
        this.id = id;
        this.stepNumber = stepNumber;
        this.description = description;
        this.durationMinutes = durationMinutes;
        this.temperatureCelsius = temperatureCelsius;
    }

    public static Result<RecipeError, ProductionStep> create(ProductionStepDraft draft) {
        if (draft.stepNumber() < 1) {
            return Result.failure(new RecipeError.ValidationFailure(
                    "Step number must be >= 1, was: " + draft.stepNumber()));
        }

        if (draft.description() == null || draft.description().isBlank()) {
            return Result.failure(new RecipeError.ValidationFailure("Step description must not be blank"));
        }

        if (draft.durationMinutes() != null && draft.durationMinutes() <= 0) {
            return Result.failure(new RecipeError.ValidationFailure(
                    "Duration minutes must be > 0, was: " + draft.durationMinutes()));
        }

        if (draft.temperatureCelsius() != null
                && (draft.temperatureCelsius() < -273 || draft.temperatureCelsius() > 1000)) {
            return Result.failure(new RecipeError.ValidationFailure(
                    "Temperature must be between -273 and 1000 Celsius, was: " + draft.temperatureCelsius()));
        }

        return Result.success(new ProductionStep(
                ProductionStepId.generate(), draft.stepNumber(), draft.description(),
                draft.durationMinutes(), draft.temperatureCelsius()
        ));
    }

    public static ProductionStep reconstitute(ProductionStepId id, int stepNumber, String description,
                                               Integer durationMinutes, Integer temperatureCelsius) {
        return new ProductionStep(id, stepNumber, description, durationMinutes, temperatureCelsius);
    }

    public ProductionStepId id() { return id; }
    public int stepNumber() { return stepNumber; }
    public String description() { return description; }
    public Integer durationMinutes() { return durationMinutes; }
    public Integer temperatureCelsius() { return temperatureCelsius; }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof ProductionStep other)) return false;
        return id.equals(other.id);
    }

    @Override
    public int hashCode() {
        return id.hashCode();
    }
}
