<?php

declare(strict_types=1);

namespace Drupal\ffmpeg_media\Trait;

use Drupal\file\FileInterface;
use Drupal\file\FileUsage\FileUsageInterface;
use Drupal\media\MediaInterface;

/**
 * Provides shared file usage checking methods.
 *
 * Classes using this trait must provide a file usage service via the
 * abstract getFileUsageService() method.
 */
trait FileUsageCheckerTrait {

  /**
   * Returns the file usage service.
   *
   * @return \Drupal\file\FileUsage\FileUsageInterface
   *   The file usage service.
   */
  abstract protected function getFileUsageService(): FileUsageInterface;

  /**
   * Checks if a file has usage from entities other than the given media.
   *
   * @param \Drupal\file\FileInterface $file
   *   File entity.
   * @param \Drupal\media\MediaInterface|null $media
   *   Media entity to exclude from usage check, or NULL.
   *
   * @return bool
   *   TRUE if other entities reference this file.
   */
  #[\NoDiscard]
  public function hasOtherFileUsage(
    FileInterface $file,
    ?MediaInterface $media,
  ): bool {
    $usage = $this->getFileUsageService()->listUsage($file);
    if ($usage === []) {
      return FALSE;
    }

    $mediaTypeId = $media?->getEntityTypeId();
    $mediaId = $media !== NULL ? (int) $media->id() : NULL;

    foreach ($usage as $entityTypes) {
      if (!is_array($entityTypes)) {
        continue;
      }
      foreach ($entityTypes as $entityType => $entities) {
        if (!is_array($entities)) {
          continue;
        }
        foreach ($entities as $id => $count) {
          if ((int) $count <= 0) {
            continue;
          }
          if ($mediaTypeId !== NULL
            && $entityType === $mediaTypeId
            && $mediaId !== NULL
            && (int) $id === $mediaId) {
            continue;
          }
          return TRUE;
        }
      }
    }

    return FALSE;
  }

  /**
   * Counts total file usage across all entities.
   *
   * @param \Drupal\file\FileInterface $file
   *   File entity.
   *
   * @return int
   *   Total usage count.
   */
  #[\NoDiscard]
  public function countFileUsage(FileInterface $file): int {
    $usage = $this->getFileUsageService()->listUsage($file);
    $total = 0;

    foreach ($usage as $entityTypes) {
      if (!is_array($entityTypes)) {
        continue;
      }
      foreach ($entityTypes as $entities) {
        if (!is_array($entities)) {
          continue;
        }
        foreach ($entities as $count) {
          $total += (int) $count;
        }
      }
    }

    return $total;
  }

  /**
   * Checks if a media entity references a file in a specific field.
   *
   * @param \Drupal\media\MediaInterface $media
   *   Media entity.
   * @param string $fieldName
   *   Field name to check.
   * @param \Drupal\file\FileInterface $file
   *   File to look for.
   *
   * @return bool
   *   TRUE if the media references the file.
   */
  #[\NoDiscard]
  public function mediaReferencesFile(
    MediaInterface $media,
    string $fieldName,
    FileInterface $file,
  ): bool {
    if (!$media->hasField($fieldName)) {
      return FALSE;
    }

    $field = $media->get($fieldName);
    if ($field->isEmpty()) {
      return FALSE;
    }

    $fileId = (int) $file->id();
    foreach ($field as $item) {
      if ((int) ($item->target_id ?? 0) === $fileId) {
        return TRUE;
      }
    }

    return FALSE;
  }

}
