<?php

namespace Drupal\acquia_contenthub\Settings;

use Drupal\acquia_contenthub\Libs\ServiceQueue\ServiceQueueHandler;
use Drupal\Core\Config\Config;
use Drupal\Core\Config\ConfigCrudEvent;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\Development\ConfigSchemaChecker;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Core\Config\TypedConfigManagerInterface;
use Psr\Log\LoggerInterface;

/**
 * Contenthub connection details from configurations.
 */
class ConnectionDetailsFromConfig implements ConnectionDetailsInterface {

  /**
   * CH admin settings configurations.
   */
  public const ACQUIA_CH_ADMIN_SETTINGS = 'acquia_contenthub.admin_settings';

  /**
   * Config factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected ConfigFactoryInterface $configFactory;

  /**
   * The typed config manger.
   *
   * @var \Drupal\Core\Config\TypedConfigManagerInterface
   */
  protected TypedConfigManagerInterface $typedManager;

  /**
   * Logger Channel.
   *
   * @var \Psr\Log\LoggerInterface
   */
  protected LoggerInterface $logger;

  /**
   * ConnectionDetailsFromConfig constructor.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory interface.
   * @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_manager
   *   The typed config manager.
   * @param \Psr\Log\LoggerInterface $logger_channel
   *   The logger channel.
   */
  public function __construct(ConfigFactoryInterface $config_factory, TypedConfigManagerInterface $typed_manager, LoggerInterface $logger_channel) {
    $this->configFactory = $config_factory;
    $this->typedManager = $typed_manager;
    $this->logger = $logger_channel;
  }

  /**
   * Provides acquia contenthub admin settings immutable configurations.
   *
   * @return \Drupal\Core\Config\ImmutableConfig
   *   Returns immutable CH admin settings configs.
   */
  private function getConfigs(): ImmutableConfig {
    return $this->configFactory->get(self::ACQUIA_CH_ADMIN_SETTINGS);
  }

  /**
   * Provides acquia contenthub admin settings editable configurations.
   *
   * @return \Drupal\Core\Config\Config
   *   Returns editable CH admin settings configs.
   */
  private function getEditableConfigs(): Config {
    return $this->configFactory->getEditable(self::ACQUIA_CH_ADMIN_SETTINGS);
  }

  /**
   * {@inheritDoc}
   */
  public function getOriginal(string $attribute): string {
    return $this->getEditableConfigs()->get($attribute) ?? '';
  }

  /**
   * {@inheritDoc}
   */
  public function setHostname(string $hostname): void {
    $this->getEditableConfigs()->set('hostname', $hostname)->save();
  }

  /**
   * {@inheritDoc}
   */
  public function getHostname(): string {
    return $this->getConfigs()->get('hostname') ?? '';
  }

  /**
   * {@inheritDoc}
   */
  public function setApiKey(string $api_key): void {
    $this->getEditableConfigs()->set('api_key', $api_key)->save();
  }

  /**
   * {@inheritDoc}
   */
  public function getApiKey(): string {
    return $this->getConfigs()->get('api_key') ?? '';
  }

  /**
   * {@inheritDoc}
   */
  public function setSecretKey(string $secret_key): void {
    $this->getEditableConfigs()->set('secret_key', $secret_key)->save();
  }

  /**
   * {@inheritDoc}
   */
  public function getSecretKey(): string {
    return $this->getConfigs()->get('secret_key') ?? '';
  }

  /**
   * {@inheritDoc}
   */
  public function setClientUuid(string $uuid): void {
    $this->getEditableConfigs()->set('origin', $uuid)->save();
  }

  /**
   * {@inheritDoc}
   */
  public function getClientUuid(): string {
    return $this->getConfigs()->get('origin') ?? '';
  }

  /**
   * {@inheritDoc}
   */
  public function setClientName(string $client_name): void {
    $this->getEditableConfigs()->set('client_name', $client_name)->save();
  }

  /**
   * {@inheritDoc}
   */
  public function getClientName(): string {
    return $this->getConfigs()->get('client_name') ?? '';
  }

  /**
   * {@inheritDoc}
   */
  public function setSharedSecret(string $shared_secret_key): void {
    $this->getEditableConfigs()->set('shared_secret', $shared_secret_key)->save();
  }

  /**
   * {@inheritDoc}
   */
  public function getSharedSecret(): string {
    return $this->getConfigs()->get('shared_secret') ?? '';
  }

  /**
   * {@inheritDoc}
   */
  public function setEventServiceUrl(string $service_url): void {
    $this->getEditableConfigs()->set('event_service_url', $service_url)->save();
  }

  /**
   * {@inheritDoc}
   */
  public function getEventServiceUrl(): string {
    return $this->getConfigs()->get('event_service_url') ?? FALSE;
  }

  /**
   * {@inheritDoc}
   */
  public function isWebhookSuppressed(): bool {
    return $this->getConfigs()->get('is_suppressed') ?? FALSE;
  }

  /**
   * {@inheritDoc}
   */
  public function suppressWebhook(): void {
    $this->getEditableConfigs()->set('is_suppressed', TRUE)->save();
  }

  /**
   * {@inheritDoc}
   */
  public function unsuppressWebhook(): void {
    $this->getEditableConfigs()->set('is_suppressed', FALSE)->save();
  }

  /**
   * {@inheritDoc}
   */
  public function setWebhook(array $webhook): void {
    $this->getEditableConfigs()->set('webhook', $webhook)->save();
  }

  /**
   * {@inheritDoc}
   */
  public function getWebhook(string $op = 'settings_url'): string {
    return $this->getConfigs()->get('webhook')[$op] ?? '';
  }

  /**
   * {@inheritDoc}
   */
  public function setWebhookUuid(string $uuid): void {
    $this->getEditableConfigs()->set('webhook.uuid', $uuid)->save();
  }

  /**
   * {@inheritDoc}
   */
  public function shouldUseSingleEntityPayload(): bool {
    return $this->getConfigs()->get('use_webhook_v1') ?? FALSE;
  }

  /**
   * {@inheritDoc}
   */
  public function toggleWebhookV1Payload(bool $enabled): void {
    $this->getEditableConfigs()->set('use_webhook_v1', $enabled)->save();
  }

  /**
   * Resets ACH configurations.
   *
   * @param array $configs
   *   ACH configuration data.
   */
  public function resetAchConfigs(array $configs = []): void {
    $this->getEditableConfigs()->setData($configs)->save();
  }

  /**
   * {@inheritDoc}
   */
  public function setMultiple(array $data): void {
    $schema_checker = new ConfigSchemaChecker($this->typedManager);
    $editable_configs = $this->getEditableConfigs();
    foreach ($data as $key => $value) {
      $editable_configs->set($key, $value);
    }
    $config_crud_event = new ConfigCrudEvent($editable_configs);
    try {
      $schema_checker->onConfigSave($config_crud_event);
      $editable_configs->save();
    }
    catch (\Exception $e) {
      $this->logger->error(sprintf("Error while saving configurations. Error message: %s", $e->getMessage()));
    }
  }

  /**
   * {@inheritDoc}
   */
  public function isOverridden(string $key = ''): bool {
    return $this->getConfigs()->hasOverrides($key);
  }

  /**
   * {@inheritDoc}
   */
  public function setSyndicationMode(string $mode): void {
    $this->getEditableConfigs()->set('syndication_mode', $mode)->save();
  }

  /**
   * {@inheritDoc}
   */
  public function getSyndicationMode(): string {
    return $this->getConfigs()->get('syndication_mode') ?? self::SYNDICATION_MODE_PUSH;
  }

  /**
   * {@inheritDoc}
   */
  public function setSyndicationLimit(int $limit): void {
    $this->getEditableConfigs()->set('limit', $limit)->save();
  }

  /**
   * {@inheritDoc}
   */
  public function getSyndicationLimit(): int {
    return $this->getConfigs()->get('limit') ?? ServiceQueueHandler::LIMIT;
  }

  /**
   * {@inheritDoc}
   */
  public function setVisibilityTimeout(string $visibility_timeout): void {
    $this->getEditableConfigs()->set('visibility_timeout', $visibility_timeout)->save();
  }

  /**
   * {@inheritDoc}
   */
  public function getVisibilityTimeout(): string {
    return $this->getConfigs()->get('visibility_timeout') ?? ServiceQueueHandler::VISIBILITY_TIMEOUT;
  }

}
