<?php

declare(strict_types=1);

namespace Drupal\ffmpeg_media\Plugin\FFmpegProcessor;

use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\ffmpeg_media\Attribute\FFmpegProcessor;
use Drupal\ffmpeg_media\Service\FFmpegExecutorInterface;
use Drupal\ffmpeg_media\ValueObject\VideoInfo;
use Symfony\Component\DependencyInjection\Attribute\Autowire;

/**
 * Processor plugin for extracting video information.
 */
#[FFmpegProcessor(
  id: 'video_info',
  label: new TranslatableMarkup('Video Info Extractor'),
  description: new TranslatableMarkup('Extracts metadata and technical information from video files.'),
  outputType: 'text',
  outputExtension: 'json',
  requiredFilters: [],
  weight: 10,
)]
final class VideoInfoProcessor extends FFmpegProcessorBase {

  /**
   * Constructs a VideoInfoProcessor object.
   *
   * @param array<string, mixed> $configuration
   *   Plugin configuration.
   * @param string $plugin_id
   *   Plugin ID.
   * @param mixed $plugin_definition
   *   Plugin definition.
   * @param \Drupal\ffmpeg_media\Service\FFmpegExecutorInterface $ffmpegExecutor
   *   FFmpeg executor service.
   * @param \Drupal\Core\File\FileSystemInterface $fileSystem
   *   The file system service.
   */
  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    #[Autowire(service: FFmpegExecutorInterface::class)]
    FFmpegExecutorInterface $ffmpegExecutor,
    #[Autowire(service: 'file_system')]
    private readonly FileSystemInterface $fileSystem,
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $ffmpegExecutor);
  }

  /**
   * {@inheritdoc}
   */
  #[\Override]
  #[\NoDiscard]
  public function process(string $inputPath, string $outputPath, array $options = []): bool {
    $videoInfo = $this->ffmpegExecutor->getVideoInfo($inputPath);

    if ($videoInfo === NULL) {
      return FALSE;
    }

    $data = [
      'path' => $videoInfo->path,
      'width' => $videoInfo->width,
      'height' => $videoInfo->height,
      'duration' => $videoInfo->duration,
      'codec' => $videoInfo->codec,
      'bitrate' => $videoInfo->bitrate,
      'format' => $videoInfo->format,
      'frame_rate' => $videoInfo->frameRate,
      'audio_codec' => $videoInfo->audioCodec,
      'audio_bitrate' => $videoInfo->audioBitrate,
      'audio_channels' => $videoInfo->audioChannels,
      'rotation' => $videoInfo->rotation,
      'is_hd' => $videoInfo->isHd,
      'is_4k' => $videoInfo->is4K,
      'aspect_ratio' => $videoInfo->aspectRatio,
      'resolution_tier' => $videoInfo->resolutionTier,
      'has_audio' => $videoInfo->hasAudio,
      'is_portrait' => $videoInfo->isPortrait,
    ];

    $json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
    if ($json === FALSE) {
      return FALSE;
    }

    return $this->fileSystem->saveData($json, $outputPath, FileExists::Replace) !== FALSE;
  }

  /**
   * Gets video info without writing to file.
   *
   * @param string $inputPath
   *   Input video file path.
   *
   * @return \Drupal\ffmpeg_media\ValueObject\VideoInfo|null
   *   Video info or NULL if unable to probe.
   */
  #[\NoDiscard]
  public function getInfo(string $inputPath): ?VideoInfo {
    return $this->ffmpegExecutor->getVideoInfo($inputPath);
  }

  /**
   * {@inheritdoc}
   */
  #[\Override]
  #[\NoDiscard]
  public function getDefaultOptions(): array {
    return [];
  }

}
