<?php

declare(strict_types=1);

namespace App\Framework\Process;

use App\Framework\Core\ValueObjects\Duration;
use App\Framework\Filesystem\ValueObjects\FilePath;
use App\Framework\Process\Exceptions\ProcessException;
use App\Framework\Process\Exceptions\ProcessTimeoutException;
use App\Framework\Process\ValueObjects\Command;
use App\Framework\Process\ValueObjects\EnvironmentVariables;

/**
 * Interface für Prozess-Ausführung.
 *
 * Ermöglicht das Ausführen von System-Prozessen mit konfigurierbaren
 * Optionen wie Umgebungsvariablen, Arbeitsverzeichnis und Timeout.
 */
interface Process
{
    /**
     * Führt einen Prozess synchron aus und wartet bis zum Ende.
     *
     * @param Command $command Das auszuführende Kommando
     * @param EnvironmentVariables|null $env Zusätzliche Umgebungsvariablen
     * @param FilePath|null $workingDirectory Arbeitsverzeichnis
     * @param Duration|null $timeout Timeout für die Ausführung
     * @return ProcessResult Das Ergebnis der Prozess-Ausführung
     *
     * @throws ProcessException wenn der Prozess nicht gestartet werden kann
     * @throws ProcessTimeoutException wenn das Timeout überschritten wird
     */
    public function run(
        Command $command,
        ?EnvironmentVariables $env = null,
        ?FilePath $workingDirectory = null,
        ?Duration $timeout = null
    ): ProcessResult;

    /**
     * Startet einen Prozess asynchron (non-blocking).
     *
     * @param Command $command Das auszuführende Kommando
     * @param EnvironmentVariables|null $env Zusätzliche Umgebungsvariablen
     * @param FilePath|null $workingDirectory Arbeitsverzeichnis
     * @return RunningProcess Der laufende Prozess
     *
     * @throws ProcessException wenn der Prozess nicht gestartet werden kann
     */
    public function start(
        Command $command,
        ?EnvironmentVariables $env = null,
        ?FilePath $workingDirectory = null
    ): RunningProcess;

    /**
     * Prüft, ob ein Kommando existiert und ausführbar ist.
     *
     * @param string $commandName Name des Kommandos (z.B. 'ffmpeg')
     * @return bool True wenn das Kommando verfügbar ist
     */
    public function commandExists(string $commandName): bool;
}
