<?php

/**
 * @file
 * Install, update functions for the social_follow_tag module.
 */

use Drupal\Core\Config\FileStorage;
use Symfony\Component\Yaml\Yaml;

/**
 * Implements hook_install().
 *
 * Perform actions related to the installation of social_follow_tag.
 */
function social_follow_tag_install() {
  // Set a higher weight to overlap templates.
  module_set_weight('social_follow_tag', 10);
  // Clear cache so that overlapped templates are used after module enabling.
  drupal_flush_all_caches();
}

/**
 * Implements hook_uninstall().
 */
function social_follow_tag_uninstall(): void {
  // Uninstall views filter configuration.
  $config = \Drupal::configFactory()->getEditable('views.view.user_admin_people');
  $config->clear('display.default.display_options.filters.social_follow_taxonomy_follow_filter');
  $config->save();
}

/**
 * Implements hook_update_dependencies().
 */
function social_follow_tag_update_dependencies(): array {
  // Update 'social_follow_tag' after 'social_user'.
  $dependencies['social_follow_tag'][12001] = [
    'social_user' => 12002,
  ];

  return $dependencies;

}

/**
 * Revert configs.
 */
function social_follow_tag_update_8801() {
  $config_files = [
    'message.template.update_node_following_tag',
  ];

  foreach ($config_files as $config_file) {
    $config = \Drupal::service('extension.list.module')->getPath('social_follow_tag') . '/config/install/' . $config_file . '.yml';

    if (is_file($config)) {
      $settings = Yaml::parse(file_get_contents($config));
      if (is_array($settings)) {
        $update_config = \Drupal::configFactory()
          ->getEditable($config_file);

        $update_config->setData($settings)->save(TRUE);
      }
    }
  }
}

/**
 * Update followtag block.
 */
function social_follow_tag_update_8802() {
  $config_path = \Drupal::service('extension.list.module')->getPath('social_follow_tag') . '/config/optional';
  $source = new FileStorage($config_path);
  /** @var \Drupal\Core\Config\StorageCacheInterface $config_storage */
  $config_storage = \Drupal::service('config.storage');
  $config_storage->write('block.block.followtag', $source->read('block.block.followtag'));
}

/**
 * Use enforced social_follow_tag module for configuration.
 */
function social_follow_tag_update_8803() {
  $config_path = \Drupal::service('extension.list.module')->getPath('social_follow_tag') . '/config/install';
  $source = new FileStorage($config_path);
  /** @var \Drupal\Core\Config\StorageCacheInterface $config_storage */
  $config_storage = \Drupal::service('config.storage');

  // List of configs.
  $configs = [
    'message.template.create_node_following_tag',
    'message.template.update_node_following_tag',
  ];

  foreach ($configs as $config) {
    $config_storage->write($config, $source->read($config));
  }
}

/**
 * Update template in existing messages.
 */
function social_follow_tag_update_8804(array &$sandbox): void {
  _social_follow_tag_update_existing_messages($sandbox);
}

/**
 * Helper callback to apply config updates.
 *
 * @param array $sandbox
 *   The update sandbox array.
 */
function _social_follow_tag_update_existing_messages(array &$sandbox): void {
  $message_storage = \Drupal::entityTypeManager()->getStorage('message');
  if (!isset($sandbox['total'])) {
    // Get all message IDs than should be updated.
    $query = $message_storage->getQuery()
      ->condition('template', 'create_node_following_tag_stream');
    $mids = $query
      ->accessCheck(FALSE)
      ->execute();
    if (empty($mids)) {
      $sandbox['#finished'] = 1;
      return;
    }

    // Set default params.
    $sandbox['total'] = $query
      ->count()
      ->accessCheck(FALSE)
      ->execute();
    $sandbox['processed'] = 0;
    $sandbox['mids'] = $mids;
  }

  $messages_per_batch = 50;
  $mids = array_slice($sandbox['mids'], $sandbox['processed'], $messages_per_batch);

  /** @var \Drupal\message\MessageInterface[] $messages */
  $messages = $message_storage->loadMultiple($mids);

  // Set new message template for existing messages.
  foreach ($messages as $message) {
    $message->set('template', 'create_node_following_tag');
    $message->save();
    $sandbox['processed']++;
  }

  $sandbox['#finished'] = $sandbox['processed'] / $sandbox['total'];
}

/**
 * Delete unnecessary message template.
 */
function social_follow_tag_update_8805() {
  \Drupal::entityTypeManager()
    ->getStorage('message_template')
    ->load('create_node_following_tag_stream')
    ->delete();
}

/**
 * Update message template for follow tag.
 */
function social_follow_tag_update_8806() {
  /** @var \Drupal\message\MessageTemplateInterface $message_template */
  $message_template = \Drupal::entityTypeManager()
    ->getStorage('message_template')
    ->load('create_node_following_tag');
  $destinations = [
    'notifications' => 'notifications',
    'email' => 'email',
  ];
  $message_template->setThirdPartySetting('activity_logger', 'activity_destinations', $destinations);
  $text = [];
  for ($i = 0; $i <= 2; ++$i) {
    $text[$i]['value'] = '<p><a href="[message:author:url:absolute]">[message:author:display-name]</a> created [social_taxonomy:indefinite_article] [social_taxonomy:content_type] <a href="[message:field_message_related_object:entity:url:absolute]">[message:node-title]</a> with the tag(s) that you follow.</p>';
    $text[$i]['format'] = 'full_html';
  }
  $message_template->set('text', $text);
  $message_template->save();
}

/**
 * Update message template "message.template.update_node_following_tag".
 *
 * Added new 'preview' and 'cta_button' tokens.
 */
function social_follow_tag_update_10301() {
  $config_file = \Drupal::service('extension.list.module')->getPath('social_follow_tag') . '/config/static/message.template.update_node_following_tag_10301.yml';
  if (is_file($config_file)) {
    $settings = Yaml::parse(file_get_contents($config_file));
    if (is_array($settings)) {
      $config = \Drupal::configFactory()
        ->getEditable('message.template.update_node_following_tag');
      $config->setData($settings)->save(TRUE);
    }
  }
}

/**
 * Update message template "message.template.create_node_following_tag_stream".
 *
 * Added new 'preview' and 'cta_button' tokens.
 */
function social_follow_tag_update_10302() {
  $config_file = \Drupal::service('extension.list.module')->getPath('social_follow_tag') . '/config/static/message.template.create_node_following_tag_stream_10302.yml';
  if (is_file($config_file)) {
    $settings = Yaml::parse(file_get_contents($config_file));
    if (is_array($settings)) {
      $config = \Drupal::configFactory()
        ->getEditable('message.template.create_node_following_tag_stream');
      $config->setData($settings)->save(TRUE);
    }
  }
}

/**
 * Revert "message.template.create_node_following_tag_stream" config.
 */
function social_follow_tag_update_10303(array &$sandbox): void {
  _social_follow_tag_update_existing_messages($sandbox);
}

/**
 * Delete "message.template.create_node_following_tag_stream" config.
 */
function social_follow_tag_update_10304(array &$sandbox): void {
  $message_template = \Drupal::entityTypeManager()
    ->getStorage('message_template')
    ->load('create_node_following_tag_stream');

  if (!is_null($message_template)) {
    $message_template->delete();
  }
}

/**
 * Add follow tags filter to "People" page.
 */
function social_follow_tag_update_11301(): void {
  // Install views filter configuration.
  $config = \Drupal::configFactory()->getEditable('views.view.user_admin_people');
  if (!empty($config->get('display.default.display_options.filters'))) {
    $config->set('display.default.display_options.filters.social_follow_taxonomy_follow_filter', [
      'id' => 'social_follow_taxonomy_follow_filter',
      'table' => 'users_field_data',
      'field' => 'social_follow_taxonomy_follow_filter',
      'relationship' => 'none',
      'group_type' => 'group',
      'admin_label' => '',
      'operator' => 'or',
      'value' => [],
      'group' => 1,
      'exposed' => TRUE,
      'expose' => [
        'operator_id' => 'social_follow_taxonomy_follow_filter_op',
        'label' => 'Following by content tags',
        'use_operator' => FALSE,
        'operator' => 'social_follow_taxonomy_follow_filter_op',
        'operator_limit_selection' => FALSE,
        'operator_list' => [],
        'identifier' => 'social_follow_taxonomy_follow_filter',
        'required' => FALSE,
        'remember' => FALSE,
        'multiple' => TRUE,
        'remember_roles' => [
          'authenticated' => 'authenticated',
        ],
        'reduce' => FALSE,
      ],
      'is_grouped' => FALSE,
      'group_info' => [
        'label' => '',
        'description' => '',
        'identifier' => '',
        'optional' => TRUE,
        'widget' => 'select',
        'multiple' => FALSE,
        'remember' => FALSE,
        'default_group' => 'All',
        'default_group_multiple' => [],
        'group_items' => [],
      ],
      'reduce_duplicates' => FALSE,
      'type' => 'select',
      'limit' => TRUE,
      'vid' => [
        'social_tagging' => 'social_tagging',
      ],
      'hierarchy' => FALSE,
      'error_message' => TRUE,
      'entity_type' => 'user',
      'plugin_id' => 'social_follow_taxonomy_follow_filter',
    ]);
    $config->save();
  }
}

/**
 * Creates a new block content type.
 */
function social_follow_tag_update_11801(): void {
  $config_path = \Drupal::service('extension.list.module')->getPath('social_follow_tag') . '/config/static';
  $source = new FileStorage($config_path);
  $entity_type_manager = \Drupal::entityTypeManager();

  // Create new block content type.
  $block_content_type_storage = $entity_type_manager->getStorage('block_content_type');
  $data = $source->read('block_content.type.most_followed_tags_11801');
  if (is_array($data)) {
    if (is_null($block_content_type = $block_content_type_storage->load($data['id']))) {
      $block_content_type_storage->create($data)->save();
    }
    else {
      /** @var \Drupal\block_content\BlockContentTypeInterface $block_content_type */
      $block_content_type->set('dependencies', $data['dependencies'])->save();
    }
  }

  // Create field storages.
  /** @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface $field_storage_config_storage */
  $field_storage_config_storage = $entity_type_manager->getStorage('field_storage_config');

  /** @var \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager */
  $field_type_manager = \Drupal::service('plugin.manager.field.field_type');
  $data = $source->read('field.storage.block_content.field_terms_11801');
  if (is_array($data)) {
    /** @var \Drupal\Core\Field\FieldItemInterface $class */
    $class = $field_type_manager->getPluginClass($data['type']);
    if (is_null($field_storage_config = $field_storage_config_storage->load($data['id']))) {
      $data['settings'] = $class::storageSettingsFromConfigData($data['settings']);
      $field_storage_config_storage->create($data)->save();
    }
    else {
      /** @var \Drupal\field\FieldStorageConfigInterface $field_storage_config */
      $field_storage_config->set('dependencies', $data['dependencies'])->save();
    }
  }

  // Create field settings.
  /** @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface $field_config_storage */
  $field_config_storage = $entity_type_manager->getStorage('field_config');
  $data = $source->read('field.field.block_content.most_followed_tags.field_terms_11801');
  if (is_array($data)) {
    if (is_null($field_config = $field_config_storage->load($data['id']))) {
      $field_config_storage->create($data)->save();
    }
    else {
      /** @var \Drupal\field\FieldConfigInterface $field_config */
      $field_config->set('dependencies', $data['dependencies'])->save();
    }
  }

  // Create new view mode for terms.
  $entity_view_mode_storage = $entity_type_manager->getStorage('entity_view_mode');
  $data = $source->read('core.entity_view_mode.taxonomy_term.followers_count_11801');
  if (is_array($data)) {
    if (is_null($entity_view_mode = $entity_view_mode_storage->load($data['id']))) {
      $entity_view_mode_storage->create($data)->save();
    }
    else {
      /** @var \Drupal\Core\Entity\EntityViewModeInterface $entity_view_mode */
      $entity_view_mode->set('dependencies', $data['dependencies'])->save();
    }
  }

  // Create/update a form/view display for the 'Most followed tags' blocks.
  $displays = [
    'entity_form_display',
    'entity_view_display',
  ];

  foreach ($displays as $display) {
    $display_storage = $entity_type_manager->getStorage($display);
    $data = $source->read("core.$display.block_content.most_followed_tags.default_11801");
    if (is_array($data)) {
      if (is_null($view_display = $display_storage->load($data['id']))) {
        $display_storage->create($data)->save();
      }
      else {
        /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $view_display */
        $view_display->setComponent('field_terms', $data['content']['field_terms']);
        $view_display->set('dependencies', $data['dependencies'])->save();
      }
    }
  }
}

/**
 * Move 'Content tags' filter in related container in admin/people.
 */
function social_follow_tag_update_12001(): string {
  /** @var \Drupal\update_helper\Updater $updateHelper */
  $updateHelper = \Drupal::service('update_helper.updater');

  // Execute configuration update definitions with logging of success.
  $updateHelper->executeUpdate('social_follow_tag', __FUNCTION__);

  // Output logged messages to related channel of update execution.
  return $updateHelper->logger()->output();
}
