package de.gecheckt.pdf.umbenenner.bootstrap.startup;

import java.util.Objects;

/**
 * Sealed result type returned by {@link CliArgumentParser#parse(String[])}.
 * <p>
 * Bootstrap evaluates the parse result to decide the next action:
 * <ul>
 *   <li>{@link Valid} — proceed with the contained {@link StartupArguments}.</li>
 *   <li>{@link Invalid} — abort with a hard startup error (exit code 1);
 *       the error message describes the specific CLI misuse to be logged.</li>
 * </ul>
 * <p>
 * The sealed hierarchy ensures that every caller must handle both cases
 * explicitly, preventing silent omission of error handling.
 */
public sealed interface StartupArgumentsParseResult {

    /**
     * Represents a successfully parsed command line.
     * <p>
     * Bootstrap may proceed normally with the contained {@link StartupArguments}.
     *
     * @param arguments the parsed startup arguments; never {@code null}
     */
    record Valid(StartupArguments arguments) implements StartupArgumentsParseResult {

        /**
         * Creates a valid parse result.
         *
         * @param arguments the parsed startup arguments; must not be {@code null}
         * @throws NullPointerException if {@code arguments} is {@code null}
         */
        public Valid {
            Objects.requireNonNull(arguments, "arguments must not be null");
        }
    }

    /**
     * Represents a failed parse due to invalid or unsupported CLI usage.
     * <p>
     * Bootstrap must treat this as a hard startup error: log the error message
     * and terminate with exit code 1. The error message is intended for the
     * operator and should be concise and actionable.
     *
     * @param errorMessage a human-readable description of the parse failure;
     *                     never {@code null}
     */
    record Invalid(String errorMessage) implements StartupArgumentsParseResult {

        /**
         * Creates an invalid parse result.
         *
         * @param errorMessage the error description; must not be {@code null}
         * @throws NullPointerException if {@code errorMessage} is {@code null}
         */
        public Invalid {
            Objects.requireNonNull(errorMessage, "errorMessage must not be null");
        }
    }
}
