<?php

declare(strict_types=1);

namespace Drupal\ffmpeg_media\Exception;

/**
 * Base exception for FFmpeg-related errors.
 */
class FFmpegException extends \RuntimeException {

  /**
   * Constructs a new FFmpegException.
   *
   * @param string $message
   *   The exception message.
   * @param int $code
   *   The exception code.
   * @param \Throwable|null $previous
   *   The previous throwable.
   * @param string|null $command
   *   The command that failed.
   * @param string|null $output
   *   The FFmpeg output.
   */
  public function __construct(
    string $message = '',
    int $code = 0,
    ?\Throwable $previous = NULL,
    public private(set) ?string $command = NULL,
    public private(set) ?string $output = NULL,
  ) {
    parent::__construct($message, $code, $previous);
  }

  /**
   * Creates an exception for a failed command.
   *
   * @param string $command
   *   The command that failed.
   * @param string $output
   *   The FFmpeg output.
   * @param int $exitCode
   *   The exit code.
   *
   * @return self
   *   New exception instance.
   */
  public static function commandFailed(string $command, string $output, int $exitCode): self {
    return new self(
      sprintf('FFmpeg command failed with exit code %d: %s', $exitCode, $output),
      $exitCode,
      NULL,
      $command,
      $output,
    );
  }

  /**
   * Creates an exception for when FFmpeg is not available.
   *
   * @return self
   *   New exception instance.
   */
  public static function notAvailable(): self {
    return new self('FFmpeg is not available or not properly configured.');
  }

  /**
   * Creates an exception for invalid input file.
   *
   * @param string $path
   *   The file path.
   *
   * @return self
   *   New exception instance.
   */
  public static function invalidInput(string $path): self {
    return new self(sprintf('Invalid input file: %s', $path));
  }

  /**
   * Creates an exception for a timeout.
   *
   * @param int $timeout
   *   The timeout in seconds.
   *
   * @return self
   *   New exception instance.
   */
  public static function timeout(int $timeout): self {
    return new self(sprintf('FFmpeg command timed out after %d seconds.', $timeout));
  }

  /**
   * Gets the failed command.
   *
   * @return string|null
   *   The command or NULL.
   */
  public function getCommand(): ?string {
    return $this->command;
  }

  /**
   * Gets the FFmpeg output.
   *
   * @return string|null
   *   The output or NULL.
   */
  public function getOutput(): ?string {
    return $this->output;
  }

}
