<?php

namespace Drupal\acquia_contenthub\Commands;

use Consolidation\AnnotatedCommand\CommandError;
use Drupal\acquia_contenthub\Client\ClientFactory;
use Drush\Commands\DrushCommands;
use Symfony\Component\Console\Helper\Table;

/**
 * Drush commands for fetching Acquia Content Hub remote settings.
 *
 * @package Drupal\acquia_contenthub\Commands
 */
class AcquiaContentHubRemoteSettingsCommands extends DrushCommands {

  /**
   * The client factory.
   *
   * @var \Drupal\acquia_contenthub\Client\ClientFactory
   */
  protected $clientFactory;

  /**
   * The Content Hub Client.
   *
   * @var \Acquia\ContentHubClient\ContentHubClient
   */
  protected $client;

  /**
   * AcquiaContentHubRemoteSettingsCommands constructor.
   *
   * @param \Drupal\acquia_contenthub\Client\ClientFactory $client_factory
   *   The client factory.
   */
  public function __construct(ClientFactory $client_factory) {
    $this->clientFactory = $client_factory;
  }

  /**
   * Checks if the client is available.
   *
   * @hook validate acquia:contenthub:remote-settings
   */
  public function checkClient(): ?CommandError {
    $this->client = $this->clientFactory->getClient();
    if ($this->client) {
      return NULL;
    }

    return new CommandError('Error trying to connect to the Content Hub. Make sure this site is registered to Content hub.');
  }

  /**
   * Returns information about /settings endpoint in a formatted manner.
   *
   * Prints information about basic account details, clients, webhooks and
   * their attached filters.
   *
   * @command acquia:contenthub:remote-settings
   * @aliases ach-rs,ach-remote-settings
   *
   * @throws \Exception
   */
  public function remoteSettings(): void {
    $settings = $this->client->getRemoteSettings();

    $this->printAccountDetails($settings);
    $this->printClients($settings['clients']);
    $this->printWebhookDetails($settings['webhooks']);
  }

  /**
   * Prints generic account details.
   *
   * @param array $settings
   *   The settings array.
   */
  protected function printAccountDetails(array $settings): void {
    $table = new Table($this->output());
    $table->setHeaders([
      'Account ID',
      'Featured',
      'Shared Secret',
    ]);
    $table->addRow([
      $settings['uuid'],
      $settings['featured'] ? 'YES' : 'NO',
      $settings['shared_secret'],
    ]);
    $table->setFooterTitle('General Account Details');
    $table->render();
  }

  /**
   * Prints the list of webhooks retrieved from settings endpoint.
   *
   * @param array $webhooks
   *   The list of webhooks.
   *
   * @throws \Exception
   */
  protected function printWebhookDetails(array $webhooks): void {
    $filters = $this->client->listFilters()['data'];

    $table = new Table($this->output());
    $table->setHeaders([
      'UUID',
      'URL',
      'Status',
      'Client UUID',
      'Client Name',
      'Filters',
    ]);
    foreach ($webhooks as $webhook) {
      // Assign names to the filters.
      $webhook['filters'] = $webhook['filters'] ?? [];
      array_walk($webhook['filters'], function (&$uuid) use ($filters) {
        $filter = array_filter($filters, function ($filter) use ($uuid) {
          return $filter['uuid'] === $uuid;
        });
        $filter = current($filter);
        if (!$filter) {
          return;
        }
        $uuid = sprintf('%s (%s)', $filter['name'], $filter['uuid']);
      });

      $table->addRow([
        $webhook['uuid'],
        $webhook['url'],
        $webhook['status'],
        $webhook['client_uuid'],
        $webhook['client_name'],
        implode("\n", $webhook['filters']),
      ]);
    }
    $table->setFooterTitle('Webhook and client relations');
    $table->render();
  }

  /**
   * Prints clients and information if there's a corresponding CDF.
   *
   * @param array $clients
   *   The array of clients returned from settings endpoint.
   *
   * @throws \Exception
   */
  protected function printClients(array $clients): void {
    $client_cdfs = $this->client->getEntities(array_column($clients, 'uuid'))->getEntities();

    $table = new Table($this->output());
    $table->setHeaders([
      'UUID',
      'Name',
      'Has client CDF',
    ]);
    foreach ($clients as $client) {
      $table->addRow([
        $client['uuid'],
        $client['name'],
        isset($client_cdfs[$client['uuid']]) ? 'YES' : 'NO',
      ]);
    }
    $table->setFooterTitle('Client list');
    $table->render();
  }

}
