<?php

namespace Drupal\acquia_contenthub_publisher\Commands;

use Acquia\ContentHubClient\Syndication\SyndicationEvents;
use Drupal\acquia_contenthub\Client\ClientFactory;
use Drupal\acquia_contenthub\Commands\Traits\ColorizedOutputTrait;
use Drupal\acquia_contenthub\Libs\Logging\ContentHubEventLogger;
use Drupal\acquia_contenthub\Libs\Traits\ResponseCheckerTrait;
use Drupal\acquia_contenthub_publisher\ContentHubReoriginator;
use Drush\Commands\DrushCommands;

/**
 * Drush command to re-originate entities from source origins to target origin.
 */
class AcquiaContentHbPublisherReoriginationCommands extends DrushCommands {

  use ResponseCheckerTrait;
  use ColorizedOutputTrait;

  /**
   * Event name.
   */
  public const EVENT_NAME = 'Re-originate Entity';

  /**
   * Event object type.
   */
  public const EVENT_OBJECT_TYPE = 'entity_multiple';

  /**
   * Content Hub reoriginator.
   *
   * @var \Drupal\acquia_contenthub_publisher\ContentHubReoriginator
   */
  protected $contentHubReoriginator;

  /**
   * Content Hub event logger.
   *
   * @var \Drupal\acquia_contenthub\Libs\Logging\ContentHubEventLogger
   */
  protected $eventLogger;

  /**
   * Content hub client.
   *
   * @var \Acquia\ContentHubClient\ContentHubClient
   */
  protected $client;

  /**
   * AcquiaContentHbPublisherReoriginationCommands constructor.
   *
   * @param \Drupal\acquia_contenthub_publisher\ContentHubReoriginator $reoriginator
   *   Content hub reoriginator.
   * @param \Drupal\acquia_contenthub\Libs\Logging\ContentHubEventLogger $event_logger
   *   CH event logger.
   * @param \Drupal\acquia_contenthub\Client\ClientFactory $client_factory
   *   CH client factory.
   *
   * @throws \Exception
   */
  public function __construct(ContentHubReoriginator $reoriginator, ContentHubEventLogger $event_logger, ClientFactory $client_factory) {
    $this->contentHubReoriginator = $reoriginator;
    $this->eventLogger = $event_logger;
    $this->client = $client_factory->getClient();
  }

  /**
   * Re-originate entities in Content Hub from one origin to another.
   *
   * @param string $origin_list
   *   Comma separated list of source origin uuids.
   * @param string $target
   *   Target origin uuid.
   * @param array $options
   *   An associative array of cli options.
   *
   * @usage acquia:contenthub:reoriginate bac07a8d-d881-45fa-949b-8b2cc8401824,cad07a8d-d881-45fa-949b-8b2cc8401835 efc07a8d-d881-45fa-949b-8b2cc8401843
   *   Reoriginates entities from bac07a8d-d881-45fa-949b-8b2cc8401824,
   *   cad07a8d-d881-45fa-949b-8b2cc8401835 to
   *   efc07a8d-d881-45fa-949b-8b2cc8401843 and deletes the origins
   *   after recreation if they didn't exist in first place.
   * @usage acquia:contenthub:reoriginate bac07a8d-d881-45fa-949b-8b2cc8401824,cad07a8d-d881-45fa-949b-8b2cc8401835 efc07a8d-d881-45fa-949b-8b2cc8401843 --no-origin-delete
   *   Reoriginates entities from bac07a8d-d881-45fa-949b-8b2cc8401824,
   *   cad07a8d-d881-45fa-949b-8b2cc8401835 to
   *   efc07a8d-d881-45fa-949b-8b2cc8401843 and keep the origins
   *   after recreation if they didn't exist in first place.
   *
   * @command acquia:contenthub:reoriginate
   * @aliases ach-reoriginate
   *
   * @throws \Exception
   */
  public function reoriginateEntities(string $origin_list, string $target, array $options = ['no-origin-delete' => FALSE]): void {
    $this->client->cacheRemoteSettings(TRUE);
    $origins = explode(',', $origin_list);

    $this->eventLogger->logEvent(
      SyndicationEvents::SEVERITY_INFO,
      self::EVENT_NAME . ' process started at ' . time(),
      self::EVENT_OBJECT_TYPE,
      self::EVENT_NAME,
      'N/A'
    );

    try {
      $responses = $this->contentHubReoriginator->reoriginateAllEntities($target, !$options['no-origin-delete'], ...$origins);

      $this->eventLogger->logEvent(
        SyndicationEvents::SEVERITY_INFO,
        self::EVENT_NAME . ' process finished at ' . time(),
        self::EVENT_OBJECT_TYPE,
        self::EVENT_NAME,
        'N/A'
      );

      foreach ($responses as $source => $response) {
        $info_message = sprintf('Reorigination request for source origin %s submitted successfully.', $source);
        $this->logger()->info($info_message);
        $this->output->writeln($info_message);

        if (!empty($response['task_id']) && !empty($response['message']) && !empty($response['request_id'])) {
          $response_details = sprintf('The progress can be inspected under task with id: %s. Request id: %s. Server response: %s.', $response['task_id'], $response['request_id'], $response['message']);
          $this->logger()->info($response_details);
          $this->output->writeln($this->toGreen($response_details));
          continue;
        }
        $error_message = sprintf('Reorigination process failed: %s', $response['error']['message']);
        $this->logger->error($error_message);
        $this->stderr()->writeln($error_message);
      }
    }
    catch (\Exception $e) {
      $error_message = 'Reorigination process failed: ' . $e->getMessage();
      $this->eventLogger->logEvent(
        SyndicationEvents::SEVERITY_ERROR,
        $error_message,
        self::EVENT_OBJECT_TYPE,
        self::EVENT_NAME,
        'N/A'
      );
      $this->logger()->error($error_message);
      $this->stderr()->writeln($error_message);
    }
  }

}
