<?php

namespace Drupal\acquia_dam\Plugin\views\field;

use Drupal\acquia_dam\AssetUpdateChecker;
use Drupal\acquia_dam\Enum\AssetStatus;
use Drupal\media\MediaInterface;
use Drupal\views\Plugin\views\field\FieldPluginBase;
use Drupal\views\ResultRow;
use Drupal\views\Views;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * AvailabilityPublishingStatusCompare.
 *
 * A views field plugin to display the results of comparing the availability
 * flag of the remote DAM asset with the publishing status of its associated
 * local media item.
 *
 * @ViewsField("availability_publishing_status_comparison")
 */
class AvailabilityPublishingStatusCompare extends FieldPluginBase {

  /**
   * The asset update checker service.
   *
   * @var \Drupal\acquia_dam\AssetUpdateChecker
   */
  protected AssetUpdateChecker $assetUpdateChecker;

  /**
   * Class constructor.
   *
   * @param array $configuration
   *   The plugin config.
   * @param string $plugin_id
   *   The plugin ID.
   * @param array $plugin_definition
   *   The plugin definition.
   * @param \Drupal\acquia_dam\AssetUpdateChecker $asset_update_checker
   *   The asset update checker service.
   */
  public function __construct(
    array $configuration,
    string $plugin_id,
    array $plugin_definition,
    AssetUpdateChecker $asset_update_checker
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->assetUpdateChecker = $asset_update_checker;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('acquia_dam.asset_update_checker'),
    );
  }

  /**
   * {@inheritdoc}
   */
  public function query() {
    $configuration = [
      'field' => 'asset_uuid',
      'left_table' => NULL,
    ];

    Views::pluginManager('join')->createInstance('standard', $configuration);
  }

  /**
   * {@inheritdoc}
   */
  public function render(ResultRow $values) {
    /** @var \Drupal\media\MediaInterface $media */
    $media = $values->_entity;

    /** @var \Drupal\acquia_dam\Plugin\media\Source\Asset $source */
    $asset = $media->getSource();

    /** @var \Drupal\acquia_dam\Enum\AssetStatus|null $asset_status */
    $asset_status = $asset->getStatus($media);

    return [
      '#theme' => 'availability_publishing_status_comparison',
      '#sync_message' => $this->getSyncMessage($media, $asset_status),
      '#sync_status' => $this->t('@status', ['@status' => $asset_status?->isInSync($media) ? 'In sync' : ($asset_status ? 'Out of sync' : 'Unknown')]),
      '#dam_status' => $this->t('@status', ['@status' => $asset_status?->getValue() ?? 'Unknown']),
      '#drupal_status' => $this->t('@status', ['@status' => $media->isPublished() ? 'Published' : 'Unpublished']),
      '#cache' => [
        'tags' => $media->getCacheTags(),
        'contexts' => $media->getCacheContexts(),
        'max-age' => $media->getCacheMaxAge(),
      ],
      '#attached' => [
        'library' => [
          'acquia_dam/availability_publishing_status_comparison',
        ],
      ],
    ];
  }

  /**
   * Generates a sync message based on the asset and media status.
   *
   * @param \Drupal\media\MediaInterface $media
   *   The media entity.
   * @param \Drupal\acquia_dam\Enum\AssetStatus|null $assetStatus
   *   The asset status.
   *
   * @return string
   *   The sync message.
   */
  private function getSyncMessage(MediaInterface $media, ?AssetStatus $assetStatus): string {
    return match (TRUE) {
      $assetStatus?->isInSync($media) => $this->t('Availability status of the DAM asset and the published status of the media item match.'),
      !$media->isPublished() && $assetStatus === AssetStatus::RELEASED => $this->t('The published status of the local media item does not align with the availability status of its remote DAM asset. Consider changing it to "Published" in Drupal.'),
      $media->isPublished() && $assetStatus === AssetStatus::UNRELEASED => $this->t('The published status of the local media item is inconsistent with the availability status of its remote DAM asset. It may be advisable to consult a Widen administrator to release this DAM asset.'),
      $media->isPublished() && $assetStatus === AssetStatus::EXPIRED => $this->t('The published status of the local media item does not correspond with the availability status of its remote DAM asset. You might need to consult a Widen administrator to update the expiry date for this DAM asset.'),
      $assetStatus === AssetStatus::DELETED => $this->t('The published status of the local media item is inconsistent with the availability status of its remote DAM asset, which has been deleted in Widen. Please replace all instances of this media item referenced in other content before deleting it.'),
      $assetStatus === NULL => $this->t('The availability status of the DAM asset is unknown. This situation arises when the media item does not possess an asset ID.'),
    };
  }

}
