<?php

use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\CssCommand;
use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Database\DatabaseExceptionWrapper;
use Drupal\Core\Database\Query\AlterableInterface;
use Drupal\Core\Database\Query\ConditionInterface;
use Drupal\Core\Database\Query\SelectInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Markup;
use Drupal\Core\Template\Attribute;
use Drupal\views\Plugin\views\pager\Full;
use Drupal\views\Plugin\views\pager\Mini;
use Drupal\views\Views;
use Drupal\views\ViewExecutable;
use Drupal\Core\Url;

/**
 * @file
 * Extend the view functions.
 */

/**
 * Implements hook_views_post_execute().
 */
function _kamihaya_cms_views_extension_views_pre_execute(ViewExecutable $view) {
  if (empty($view->pager) || !($view->pager instanceof Full)) {
    return;
  }

  // $view->get_total_rows = TRUE;
}

/**
 * Implements hook_views_post_execute().
 */
function kamihaya_cms_views_extension_views_post_execute(ViewExecutable $view) {
  if (empty($view->pager) || !($view->pager instanceof Mini) || $view->get_total_rows) {
    return;
  }

  $count_query = $view->build_info['count_query'];

  if (!($count_query instanceof SelectInterface)) {
    return;
  }
  $count_query->addMetaData('view', $view);

  if (empty($view->query->options['disable_sql_rewrite'])) {
    $base_table_data = Views::viewsData()->get($view->storage->get('base_table'));
    if (isset($base_table_data['table']['base']['access query tag'])) {
      $access_tag = $base_table_data['table']['base']['access query tag'];
      $count_query->addTag($access_tag);
    }

    if (isset($base_table_data['table']['base']['query metadata'])) {
      foreach ($base_table_data['table']['base']['query metadata'] as $key => $value) {
        $count_query->addMetaData($key, $value);
      }
    }
  }

  if ($count_query) {
    $count_query->preExecute();

    // Build the count query.
    $count_query = $count_query->countQuery();

    try {
      $view->pager->executeCountQuery($count_query);
      $view->pager->updatePageInfo();
    }
    catch (DatabaseExceptionWrapper $e) {
      if (!empty($view->live_preview)) {
        Drupal::messenger()->addError($e->getMessage());
      }
      else {
        throw new DatabaseExceptionWrapper("Exception in {$view->storage->label()}[{$view->storage->id()}]: {$e->getMessage()}");
      }
    }
  }
}

/**
 * Implements hook_views_pre_render().
 */
function kamihaya_cms_views_extension_views_pre_render(ViewExecutable $view) {
  // Check if the view uses the 'infinite_scroll' pager and has a VBO field.
  $is_vbo = FALSE;
  $is_infinite_scroll = FALSE;

  // Check if the view is using the Infinite Scroll pager.
  if (!empty($view->display_handler->getOption('pager'))) {
    $pager_options = $view->display_handler->getOption('pager');

    // Check if Infinite Scroll is enabled.
    if (!empty($pager_options['type']) && $pager_options['type'] === 'infinite_scroll') {
      $is_infinite_scroll = TRUE;
    }
  }

  // Check if any field in the view is a VBO operation.
  foreach ($view->field as $field) {
    if ($field->definition['id'] === 'views_bulk_operations_bulk_form') {
      $is_vbo = TRUE;
      break;
    }
  }
  // Fetch redirect path from VBO field configuration.
  $compare_path = '';
  $fields = $view->display_handler->getOption('fields') ?? [];

  foreach ($fields as $field) {
    // Check for the VBO field.
    if ($field['id'] === 'views_bulk_operations_bulk_form' && !empty($field['selected_actions'])) {
      foreach ($field['selected_actions'] as $action) {
        if (!empty($action['action_id']) && $action['action_id'] === 'vbo_redirect_to_view_action') {
          // Get the view and display ID from the configuration.
          $redirect_view_id = $action['preconfiguration']['redirect_view'] ?? '';
          if (strpos($redirect_view_id, ':') !== FALSE) {
            [$redirect_view, $display_id] = explode(':', $redirect_view_id);
            // Load the target view.
            $target_view = Views::getView($redirect_view);
            if ($target_view && $target_view->access($display_id)) {
              $target_view->setDisplay($display_id);

              // Get language info.
              $language_manager = \Drupal::languageManager();
              $langcode = $language_manager->getCurrentLanguage()->getId();
              $default_langcode = $language_manager->getDefaultLanguage()->getId();
              // Load the language negotiation configuration and get the URL prefix
              // for the current language. This prefix is defined under
              // "Detection and selection → Language from the URL (Path prefix or domain)".
              $config = \Drupal::config('language.negotiation');
              $langcode_prefix = $config->get('url.prefixes.' . $langcode);

              // Get base path from the view.
              $base_path = $target_view->display_handler->getPath();
              $clean_path = ltrim($base_path, '/');

              // Add langcode to the path if it's not default.
              if ($langcode !== $default_langcode) {
                $clean_path = $langcode_prefix . '/' . $clean_path;
              }

              // Generate absolute URL.
              $compare_path = Url::fromUserInput('/' . $clean_path, ['absolute' => TRUE])->toString();
              break 2; // Exit both loops once a valid path is found.
            }
          }
        }
      }
    }
  }
  // If both VBO and Infinite Scroll are used, re-apply vbo events jss.
  // Attach custom JS and settings if VBO + Infinite Scroll are enabled.
  if ($is_vbo && $is_infinite_scroll) {
    $view->element['#attached']['library'][] = 'kamihaya_cms_views_extension/reapply-vbo-events';

    if (!empty($compare_path)) {
      $view->element['#attached']['drupalSettings']['vboCompareRedirect'] = [
        'comparePath' => $compare_path,
      ];
    }
  }

  if (empty($view->pager) || !($view->pager instanceof Full)) {
    return;
  }
  $view->pager->options['quantity'] = 7;
}

/**
 * Implements hook_query_TAG_alter().
 */
function kamihaya_cms_views_extension_query_reduce_duplicate_term_alter(AlterableInterface $query) {
  $field_names = ['tid', 'weight', 'id'];
  $fields = &$query->getFields();
  $order_by = &$query->getOrderBy();
  $order_by_keys = array_keys($order_by);
  $order_by_values = array_values($order_by);
  foreach($fields as $name => $field) {
    if (strpos($name, 'parent_tid') === FALSE && !in_array($field['field'], $field_names)) {
      continue;
    };
    if (array_key_exists($name, $order_by)) {
      $index = array_search($name, $order_by_keys);
      $order_by_keys[$index] = "{$field['table']}.{$field['field']}";
      $order_by = array_combine($order_by_keys, $order_by_values);
      unset($order_by[$name]);
    }
    unset($fields[$name]);
  }
}

/**
 * Implements hook_query_TAG_alter().
 */
function kamihaya_cms_views_extension_query_reduce_duplicate_node_alter(AlterableInterface $query) {
  $field_names = ['nid', 'delta', 'id'];
  $fields = &$query->getFields();
  $order_by = &$query->getOrderBy();
  $order_by_keys = array_keys($order_by);
  $order_by_values = array_values($order_by);
  foreach($fields as $name => $field) {
    if (!in_array($field['field'], $field_names)) {
      continue;
    };
    if (array_key_exists($name, $order_by)) {
      $index = array_search($name, $order_by_keys);
      $order_by_keys[$index] = "{$field['table']}.{$field['field']}";
      $order_by = array_combine($order_by_keys, $order_by_values);
      unset($order_by[$name]);
    }
    unset($fields[$name]);
  }
}

/**
 * Add the current language condition to the query.
 *
 * @param \Drupal\Core\Database\Query\AlterableInterface $query
 *   The query object.
 */
function kamihaya_cms_views_extension_query_current_language_alter(AlterableInterface $query) {
  $tables = &$query->getTables();
  if (!array_key_exists('node_field_data', $tables)) {
    return;
  }
  foreach ($tables as $alias => $table) {
    if ($table['table'] !== 'media_field_data') {
      continue;
    }
    $media_alias = $alias;
    break;
  }
  if (empty($media_alias)) {
    return;
  }

  $media_table = $tables[$media_alias];
  foreach ($tables as $alias => $table) {
    if ($table['table'] === 'node_field_data' || $table['table'] === 'media_field_data' || empty($table['condition']) || strpos($media_table['condition'], "$alias.") === FALSE) {
      continue;
    }
    $media_ref_table = $tables[$alias]['table'];
    break;
  }

  if (empty($media_ref_table)) {
    return;
  }

  // Add the language condition.
  $langcode = \Drupal::languageManager()->getCurrentLanguage()->getId();
  $default_langcode = \Drupal::languageManager()->getDefaultLanguage()->getId();

  if ($langcode === $default_langcode) {
    $query->condition("$media_ref_table.langcode", $langcode);
    return;
  }

  $connection = \Drupal::database();
  // Create a subquery to check if the media is translated.
  $subquery = $connection->select($media_ref_table, 'mrt');
  $subquery->addField('mrt', 'entity_id');
  $subquery->where("mrt.langcode = '$langcode'");
  $subquery->where("mrt.entity_id = node_field_data.nid");

  // Add the language condition.
    $query->where("($media_ref_table.langcode = :langcode
      OR ($media_ref_table.langcode = :default_langcode
      AND NOT EXISTS (" . $subquery->__toString()  . ")))", [
    ':langcode' => $langcode,
    ':default_langcode' => $default_langcode,
  ]);
}

/**
 * Implements hook_query_TAG_alter().
 */
function kamihaya_cms_views_extension_query_multiple_media_field_union_alter(AlterableInterface $query) {
  $tables = &$query->getTables();
  $media_aliases = [];
  // Find media_field_data table.
  foreach($tables as $alias => $table) {
    if ($table['table'] !== 'media_field_data') {
      continue;
    }
    $media_aliases[] = $alias;
  }
  if (empty($media_aliases) || count($media_aliases) != 2) {
    return;
  }

  // Set the union query before working on the base query.
  $union_query = unserialize(serialize($query));
  // Working on the base query.
  _kamihaya_cms_views_extension_media_query_for_union($query, $media_aliases[1], FALSE);
  // Add the current language condition to the base query.
  kamihaya_cms_views_extension_query_current_language_alter($query);
  $fields = &$query->getFields();
  $field_alias = array_keys($fields);
  $order_by = &$query->getOrderBy();

  // Working on the union queries.
  _kamihaya_cms_views_extension_media_query_for_union($union_query, $media_aliases[0]);
  // Add the current language condition to the union query.
  kamihaya_cms_views_extension_query_current_language_alter($union_query);
  $union_fields = &$union_query->getFields();
  $field_values = array_values($union_fields);
  // Align the field alias to the base query.
  $union_fields = array_combine($field_alias, $field_values);
  foreach($union_fields as $alias => &$field) {
    $field['alias'] = $alias;
  }
  // Change the order by fields to sort data after the result of the base query.
  foreach ($order_by as $alias => $order) {
    if (!array_key_exists($alias, $union_fields)) {
      continue;
    }
    $field = &$union_fields[$alias];
    $union_query->addExpression("({$field['table']}.{$field['field']} + 999999)", $alias);
    unset($union_fields[$alias]);
  }

  // Change the order of order by fields in the base query.
  foreach ($order_by as $alias => $order) {
    if (!array_key_exists($alias, $fields)) {
      continue;
    }
    $field = &$fields[$alias];
    unset($fields[$alias]);
    $fields[$alias] = $field;
  }

  // Add the union query to the base query.
  $query->union($union_query);
}

/**
 * Implements hook_query_TAG_alter().
 */
function kamihaya_cms_views_extension_query_allow_media_empty_alter(AlterableInterface $query) {
  $conditions = $query->conditions();
  $tables = $query->getTables();
  $media_alias = [];
  // Find media_field_data table.
  foreach($tables as $alias => $table) {
    if (strpos($table['table'], 'media_') !== 0) {
      continue;
    }
    $media_alias[] = $alias;
  }

  if (empty($conditions)) {
    return;
  }
  foreach ($conditions as &$condition) {
    // Check if the condition is related to media_field_data.
    if (!is_array($condition) || empty($condition['field']) || !($condition['field'] instanceof ConditionInterface)) {
      continue;
    }
    $cons = &$condition['field']->conditions();
    foreach ($cons as $idx => &$con) {
      if (!is_array($con) || empty($con['field']) || !($con['field'] instanceof ConditionInterface)) {
        continue;
      }
      $cons2 = &$con['field']->conditions();
      foreach ($cons2 as $idx2 => &$con2) {
        if (!is_array($con2) || empty($con2['field']) || !is_string($con2['field'])) {
          continue;
        }
        // Check if the condition is related to media tables.
        foreach ($media_alias as $alias) {
          if (strpos($con2['field'], "$alias.") === FALSE) {
            continue;
          }
          // If the condition is related to media tables, allow empty media.
          $field = $con2['field'];
          $or = $query->orConditionGroup();
          $or->isNull($field);
          $or->condition($field, $con2['value'], $con2['operator']);
          $con['field']->condition($or);
          unset($cons2[$idx2]);
        }
      }
    }
  }
}

/**
 * Check if the condition is related to the remove tables.
 *
 * @param array $condition
 *   The condition array.
 * @param array $remove_tables
 *   The tables to be removed.
 * @return bool
 *   TRUE if the condition is related to the remove tables.
 */
function _kamihaya_cms_views_extension_check_condition(array $condition, array $remove_tables) {
  if (!is_array($condition) || empty($condition['field']) || !is_string($condition['field'])) {
    return FALSE;
  }
  foreach($remove_tables as $table) {
    if (strpos($condition['field'], "$table.") === FALSE) {
      continue;
    }
    return TRUE;
  }
}

/**
 * Update the query for union.
 *
 * @param SelectInterface $query
 *   The union query.
 * @param string $media_alias
 *   The media alias.
 * @param bool $union
 *   TRUE if the query is for union.
 */
function _kamihaya_cms_views_extension_media_query_for_union(SelectInterface $query, $media_alias, $union = TRUE) {
  $remove_tables = [];
  $tables = &$query->getTables();
  $media_table = $tables[$media_alias];
  $fields = &$query->getFields();
  $conditions = &$query->conditions();
  $order_by = &$query->getOrderBy();
  if ($union) {
    $query->range(NULL, NULL);
    $order_by = [];
  }
  // Remove tables for other query.
  foreach($tables as $alias => &$table) {
    if ($table['table'] === 'node_field_data' || empty($table['condition'])) {
      continue;
    }
    if ($alias === $media_alias) {
      $remove_tables[] = $alias;
      unset($tables[$alias]);
      continue;
    }
    if (strpos($media_table['condition'], "{$alias}.") !== FALSE) {
      $remove_tables[] = $alias;
      unset($tables[$alias]);
      continue;
    }
  }

  // Remove fields for other query.
  foreach($fields as $name => &$field) {
    if (!in_array($field['table'], $remove_tables)) {
      continue;
    }
    if (array_key_exists($name, $order_by)) {
      unset($order_by[$name]);
    }
    unset($fields[$name]);
  }

  // Remove conditions for other query.
  foreach($conditions as $idx => &$condition) {
    if (!is_array($condition) || empty($condition['field'])) {
      continue;
    }

    if (is_string($condition['field']) && _kamihaya_cms_views_extension_check_condition($condition, $remove_tables)) {
      unset($conditions[$idx]);
      continue;
    }
    if (!is_object($condition['field'])) {
      continue;
    }
    $cons = &$condition['field']->conditions();
    foreach($cons as $idx1 => &$con) {
      if (!is_array($con) || empty($con['field'])) {
        continue;
      }

      if (is_string($con['field']) && _kamihaya_cms_views_extension_check_condition($con, $remove_tables)) {
        unset($cons[$idx1]);
        continue;
      }
      if (!is_object($con['field'])) {
        continue;
      }
      $cons2 = &$con['field']->conditions();
      foreach($cons2 as $idx2 => &$con2) {
        if (!is_array($con2) || empty($con2['field'])) {
          continue;
        }

        if (is_string($con2['field']) && _kamihaya_cms_views_extension_check_condition($con2, $remove_tables)) {
          unset($cons2[$idx2]);
          continue;
        }
        if (!is_object($con2['field'])) {
          continue;
        }
        $cons3 = &$con2['field']->conditions();
        foreach($cons3 as $idx3 => &$con3) {
          if (!is_array($con3) || empty($con3['field'])) {
            continue;
          }

          if (is_string($con3['field']) && _kamihaya_cms_views_extension_check_condition($con3, $remove_tables)) {
            unset($cons3[$idx3]);
            continue;
          }
        }
      }
    }
  }
}

/**
 * Update condition field and value.
 *
 * @param array $condition
 *   The condition array.
 * @param string $alias
 *   The alias to be replaced.
 * @param string $replace
 *   The alias to replace.
 * @param string $field
 *   The field to be replaced.
 */
function _kamihaya_cms_views_extension_update_condition(array &$condition, $alias, $replace, $field = NULL) {
  if (strpos($condition['field'], "$alias.") !== FALSE) {
    $condition['field'] = str_replace("$alias.", "$replace.", $condition['field']);
  }
  if (!empty($field) && strpos($condition['field'], $field) === 0) {
    $condition['field'] = $replace . $condition['field'];
  }
  if (is_array($condition['value']) || empty($condition['value'])) {
    return;
  }
  if (strpos($condition['value'], "$alias.") !== FALSE) {
    $condition['value'] = str_replace("$alias.", "$replace.", $condition['value']);
  }
  if (!empty($field) && strpos($condition['value'], $field) === 0) {
    $condition['value'] = $alias . $condition['value'];
  }
}

/**
 * Implements hook_preprocess_views_view_table().
 */
function kamihaya_cms_views_extension_preprocess_views_view_table(&$variables) {
  $view = $variables['view'];
  $rows = &$variables['rows'];

  if ($view->getStyle()->getPluginId() === 'kamihaya_responsive_table') {
    $variables['#attached']['library'][] = 'kamihaya_cms_views_extension/responsive_table';
    foreach ($rows as $idx => &$row) {
      foreach ($row['columns'] as $field_name => &$col) {
        if (empty($variables['header'][$field_name]) || $field_name === 'views_bulk_operations_bulk_form') {
          continue;
        }
        $label = $variables['header'][$field_name]['content'];
        if (empty($col['fields'][0])) {
          continue;
        }
        $label_value = !empty($label) ? "<b class='responsive-label'>$label</b>" : '';
        if (empty($label)) {
          $col['attributes']->addClass('no-label');
        }
        if (!empty($col['content']) && !empty($col['content'][0]['field_output']['#markup'])) {
          if ($col['content'][0]['field_output']['#markup'] instanceof Markup) {
            $text = $col['content'][0]['field_output']['#markup']->__toString();
            $col['content'][0]['field_output']['#markup'] = Markup::create("$label_value<div class='field-value'>$text</div>");
          }
          else {
            $text = $col['content'][0]['field_output']['#markup'];
            $col['content'][0]['field_output']['#markup'] = "$label_value<div class='field-value'>$text</div>";
          }
        }
        else {
          $col['content'] = [
            [
              'field_output' => [
                '#markup' => "$label_value<div class='field-value'></div>",
              ]
            ],
          ];
        }
      }
    }
  }
}

/**
 * Implements hook_form_views_exposed_form_alter().
 */
function kamihaya_cms_views_extension_form_views_exposed_form_alter(array &$form, FormStateInterface $form_state) {
  // Disable cache for this form.
  // @see https://www.drupal.org/project/drupal/issues/3395776.
  $form['#cache']['max-age'] = 0;
  // Get current request
  $request = \Drupal::request();
  // Set sort_by option to default.
  if (!empty($form['sort_by']) && empty($request->query->get('sort_by') && array_key_exists(0, $form['sort_by']['#options']))) {
    $form['sort_by']['#value'] = 0;
  }
  // Add AJAX functionality to the exposed fields.
  kamihaya_cms_views_extension_add_ajax($form, $form_state);

  /*`@var Drupal\views\ViewExecutable $view */
  $view = $form_state->get('view');
  $filters = $view->getHandlers('filter');
  if (empty($filters)) {
    return;
  }

  $request = \Drupal::request();
  if (!empty($request->query->all())) {
    // If the request contains any query parameters, do nothing.
    return;
  }

  $user_input = $form_state->getUserInput();
  foreach ($filters as $name => $filter) {
    // Check if the filter is a boolean filter.
    if (empty($filter['plugin_id']) || $filter['plugin_id'] !== 'boolean' || empty($filter['exposed'] )) {
      continue;
    }
    if (empty($filter['default_check'])) {
      continue;
    }
    // If the default check is set to TRUE, set the default value of the checkbox to TRUE.
    $form[$name]['#default_value'] = TRUE;
    $user_input[$name] = TRUE;
    // Set the user input to the form state.
    $form_state->setUserInput($user_input);
  }
}

/**
 * Add AJAX functionality to the exposed fields in the view.
 *
 * @param array $form
 *   The form array.
 * @param Drupal\Core\Form\FormStateInterface $form_state
 *   The form state.
 */
function kamihaya_cms_views_extension_add_ajax(array &$form, FormStateInterface $form_state) {
  foreach ($form as $key => &$value) {
    if ($key === 'filter_grouping' && is_array(($value))) {
      kamihaya_cms_views_extension_add_ajax($value, $form_state);
      continue;
    }
    if (!is_array($value) || strpos($key, 'field_') !== 0) {
      continue;
    }

    if (isset($value['#options']) && empty($value['#options'])) {
      if (!empty($value['#group']) && $value['#group'] !== 'secondary') {
        $form[$value['#group']]['#attributes']['style'][] = 'display: none';
      }
    }
    // @see KamihayaTaxonomyViewsFilterTrait.
    if (empty($value['#related_filter'])) {
      continue;
    }
    // This ID will be used to display data received from the AJAX response.
    $id = str_replace('_', '-', (!empty($value['#group']) ? $value['#group'] : $key));
    $class = $value['#type'] === 'checkboxes' ? ' .form-checkboxes' : '';
    // Assign fixed ID to the wrapper class.
    if (!empty($value['#group'])) {
      $form[$value['#group']]['#id'] = $id;
    }
    else {
      $value['#wrapper_attributes']['id'] = $id;
    }
    $related_filter = $value['#related_filter'];
    foreach ($related_filter as $filter) {
      // Initiate AJAX only once for the parent filter.
      if (empty($form[$filter]['#ajax'])) {
        $form[$filter]['#ajax'] = [
          'callback' => 'kamihaya_cms_views_extension_ajax_callback',
          'event' => 'change',
          'wrapper' => [],
          'progress' => [
            'type' => 'throbber',
            'message' => '',
          ],
        ];
      }
      // If there are multiple field options which needs to be updated, specify the wrappers for each field.
      $target = $key;
      $form[$filter]['#ajax']['wrapper'][$target] =  '#' . $id . $class;
    }
  }
}

/**
 * Ajax callback for exposed form.
 *
 * @param array $form
 *   The form array.
 * @param FormStateInterface $form_state
 *  The form state.
 */
function kamihaya_cms_views_extension_ajax_callback(array &$form, FormStateInterface $form_state) {
  $target = $form_state->getTriggeringElement();
  // Contains wrapper for each of the child filters.
  $elements = $target['#ajax']['wrapper'];
  $renderer = \Drupal::service('renderer');
  $visible_filters = [];
  $response = new AjaxResponse();
  foreach ($elements as $name => $id) {
    // @see https://www.drupal.org/project/field_group/issues/3201653
    if (isset($form[$name]['#group'])) {
      // Render function returns empty html if #group attribute is present, so remove this.
      unset($form[$name]['#group']);
    }
    $field = &$form[$name];
    if (empty($field) && !empty($form['filter_grouping']) && !empty($form['filter_grouping'][$name])) {
      $field = &$form['filter_grouping'][$name];
    }

    if (empty($field)) {
      continue;
    }
    $form_element = explode(' ', $id);
    if (isset($field['#options']) && empty($field['#options'])) {
      $hide = new CssCommand($form_element[0],['display' => 'none']);
      $response->addCommand($hide);
    }
    else {
      $show = new CssCommand($form_element[0],['display' => 'block']);
      $response->addCommand($show);
      $html = $renderer->render($field);
      $command = new ReplaceCommand("$id", $html);
      $response->addCommand($command);
      $visible_filters[] = $name;
    }
  }
  if (!empty($visible_filters) && !empty($form['secondary']['#attributes']['class']) && in_array('kamihaya-show-filter-bar', $form['secondary']['#attributes']['class'])) {
    $response->addCommand(new InvokeCommand('#secondary-filters', 'removeClass', ['kamihaya-hide-filter-bar']));
    $response->addCommand(new InvokeCommand('#secondary-filters', 'addClass', ['kamihaya-show-filter-bar']));
  }
  if (empty($visible_filters) && !empty($form['secondary']['#attributes']['class']) && in_array('kamihaya-hide-filter-bar', $form['secondary']['#attributes']['class'])) {
    $response->addCommand(new InvokeCommand('#secondary-filters', 'removeClass', ['kamihaya-show-filter-bar']));
    $response->addCommand(new InvokeCommand('#secondary-filters', 'addClass', ['kamihaya-hide-filter-bar']));
  }
  $submit_command = new InvokeCommand('input.form-submit[data-bef-auto-submit-click]', 'click');
  $response->addCommand($submit_command);
  return $response;
}

/**
 * Implements hook_views_plugins_filter_alter().
 */
function kamihaya_cms_views_extension_views_plugins_filter_alter(array &$plugins) {
  if (!empty($plugins['taxonomy_index_tid'])) {
    $plugins['taxonomy_index_tid']['class'] = $plugins['kamihaya_taxonomy_index_tid']['class'];
  }
  if (!empty($plugins['taxonomy_index_tid_depth'])) {
    $plugins['taxonomy_index_tid_depth']['class'] = $plugins['kamihaya_taxonomy_index_tid_depth']['class'];
  }
  if (!empty($plugins['datetime'])) {
    $plugins['datetime']['class'] = $plugins['kamihaya_date']['class'];
  }
  if (!empty($plugins['boolean'])) {
    $plugins['boolean']['class'] = $plugins['kamihaya_boolean']['class'];
  }
  if (!empty($plugins['combine'])) {
    $plugins['combine']['class'] = $plugins['kamihaya_combine']['class'];
  }
}

/**
 * Implements hook_views_plugins_field_alter().
 */
function kamihaya_cms_views_extension_views_plugins_field_alter(array &$plugins) {
  if (!empty($plugins['json_data'])) {
    $plugins['json_data']['class'] = $plugins['kamihaya_json_data']['class'];
  }
  if (!empty($plugins['views_bulk_operations_bulk_form'])) {
    $plugins['views_bulk_operations_bulk_form']['class'] = $plugins['kamihaya_views_bulk_operation_form']['class'];
  }
}

/**
 * Implements hook_views_plugins_exposed_form_alter().
 */
function kamihaya_cms_views_extension_views_plugins_exposed_form_alter(array &$plugins) {
  if (!empty($plugins['bef'])) {
    $plugins['bef']['class'] = $plugins['kamihaya_exposed_form']['class'];
  }
}

/**
 * Implements hook_views_plugins_exposed_form_alter().
 */
function kamihaya_cms_views_extension_views_plugins_style_alter(array &$plugins) {
  if (!empty($plugins['flipped_table'])) {
    $plugins['flipped_table']['class'] = $plugins['kamihaya_flipped_table']['class'];
  }
}

/**
 * Implements hook_preprocess_views_view_table().
 */
function kamihaya_cms_views_extension_preprocess_flag(&$variables) {
  $default_language = \Drupal::languageManager()->getDefaultLanguage();
  $default_lang_code = $default_language->getId();
  $variables['#attached']['library'][] = 'kamihaya_cms_views_extension/flag-block-refresh';
  $variables['#attached']['drupalSettings']['default_language'] = $default_lang_code;
  $route = Drupal::routeMatch()->getRouteName();
  if (strpos($route, 'view.') !== 0) {
    return;
  }
  $array = explode('.', $route);
  if (count($array) < 3) {
    return;
  }
  $view = Views::getView($array[1]);
  $view->setDisplay($array[2]);
  $display = $view->display_handler;
  if ($display->ajaxEnabled()) {
    return;
  }
  if (empty($variables['attributes']['class']) || $idx = array_search('use-ajax', $variables['attributes']['class'])) {
    return;
  }
  unset($variables['attributes']['class'][$idx]);
}

/**
 * Implements hook_preprocess_views_view_flipped_table().
 */
function kamihaya_cms_views_extension_preprocess_views_view_flipped_table(array &$variables) {
  $view = $variables['view'];
  $handler = $view->style_plugin;
  $row_class = $handler->options['row_class'];
  $table_layout = $handler->options['table_layout'];
  $th_width = $handler->options['th_width'];
  $td_width = $handler->options['td_width'];
  $no_value_text = $handler->options['no_value_text'];
  $variables['table_layout'] = $table_layout;
  $variables['th_width'] = $th_width;
  $variables['td_width'] = $td_width;
  if (empty($row_class) && empty($no_value_text)) {
    return;
  }
  foreach ($variables['rows_flipped'] as $idx => &$row) {
    if (!empty($row_class)) {
      if (empty($row['attributes'])) {
        $row['attributes'] = new Attribute();
      }
      $row['attributes']->addClass($row_class);
    }
    if (empty($no_value_text) || empty($row['columns'])) {
      continue;
    }
    foreach ($row['columns'] as &$col) {
      if (empty($col['content'])) {
        $col['content'][] = [
          'field_output' => Markup::create(t($no_value_text)),
        ];
      }
    }
  }
}

/**
 * Implements hook_views_data().
 */
function kamihaya_cms_views_extension_views_data_alter(array &$data): void {
  $data['views']['table']['group'] = t('Kamihaya Views');
  $data['views']['table']['join'] = [
    // #global is a special flag which allows a table to appear all the time.
    '#global' => [],
  ];

  $data['views']['kamihaya_cms_views_extension_quantity'] = [
    'title' => t('Quantity'),
    'help' => t('Allow to estimate the price based on quantity.'),
    'field' => [
      'id' => 'kamihaya_cms_views_extension_quantity',
    ],
  ];
  $data['views']['kamihaya_cms_views_extension_estimate'] = [
    'title' => t('Price'),
    'help' => t('Display the estimate.'),
    'field' => [
      'id' => 'custom',
    ],
  ];

}

/**
 * Implements hook_query_TAG_alter() for 'reduce_duplicate_paragraph' tag.
 *
 * This hook removes the 'paragraph.id' field from the SELECT clause
 * to prevent duplicate paragraph results in Views using paragraph relationships.
 * Add the 'reduce_duplicate_paragraph' tag to the query settings in the view.
 *
 * @param \Drupal\Core\Database\Query\AlterableInterface $query
 *   The query object being altered.
 */
function kamihaya_cms_views_extension_query_reduce_duplicate_paragraph_alter(AlterableInterface $query) {
  // Get the list of fields in the query.
  $fields = &$query->getFields();

  // Loop through the fields and remove any that are paragraph.id.
  foreach ($fields as $alias => $field) {
    if (!empty($field['table']) && !empty($field['field']) &&
        str_starts_with($field['table'], 'paragraph') &&
        $field['field'] === 'id') {
      unset($fields[$alias]);
    }
  }
}
