<?php

use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\node\Entity\NodeType;
use Drupal\node\NodeInterface;
use Drupal\views_flipped_table\Plugin\views\style\FlippedTable;

/**
 * @file
 * hook implementation for Content type.
 */

/**
 * Implements hook_preprocess_layout().
 */
function kamihaya_cms_content_type_preprocess_layout(array &$variables) {
  // Get the current node.
  $node = \Drupal::routeMatch()->getParameter('node');
  if (empty($node)) {
    return;
  }
  if (is_numeric($node)) {
    $node = \Drupal::entityTypeManager()->getStorage('node')->load($node);
  }
  if (!$node instanceof NodeInterface) {
    return;
  }

  /** @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface $display_repository */
  $display_repository = \Drupal::service('entity_display.repository');

  // Get the view display.
  $view_display = $display_repository->getViewDisplay($node->getEntityTypeId(), $node->bundle(), 'default');

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

  // Create anchor links for headings.
  kamihaya_cms_content_type_create_headins_anchor_link($node, $variables);


  // Create anchor links for field groups.
  kamihaya_cms_content_type_create_anchor_link($view_display, $variables);
}

/**
 * Create anchor links for field groups.
 *
 * @param \Drupal\node\NodeInterface $node
 *   The node to check.
 * @param array $variables
 *   The variables to add the anchor links to.
 */
function kamihaya_cms_content_type_create_anchor_link(EntityViewDisplayInterface $view_display, array &$variables) {
  // Get the field group settings.
  $field_group_settings = $view_display->getThirdPartySettings('field_group');
  if (empty($field_group_settings)) {
    return;
  }
  $sticky = FALSE;
  foreach($variables['content'] as $name => &$element) {
    if (is_array($element) && array_key_exists('anchor_links', $element)) {
      $anchor_links = &$element['anchor_links'];
    }
    if (strpos($name, 'group_') !== 0 || empty($element['#id']) || empty($element['#title']) || (isset($element['#access']) && empty($element['#access']))) {
      continue;
    }
    if (!empty($element['#attributes']['class']) && in_array('full-width', $element['#attributes']['class'])) {
      $full_width = TRUE;
    }
    if (!$sticky && !empty($field_group_settings[$name]['format_settings']['anchor_link_sticky'])) {
      $sticky = TRUE;
    }

    $links[$element['#id']] = [
      'title' => $element['#title'],
      'url' => Url::fromUserInput("#{$element['#id']}"),
      'attributes' => [
        'class' => ['btn', 'btn-primary'],
      ],
    ];

    if (!empty($field_group_settings[$name]['format_settings']['anchor_link_sticky'])) {
      $links[$element['#id']]['attributes']['class'][] = 'sticky-item';
    }
  }
  if (empty($anchor_links) && !empty($variables['content']['anchor_links'])) {
    $anchor_links = &$variables['content']['anchor_links'];
  }
  if (empty($links) || empty($anchor_links)) {
    return;
  }
  $anchor_links['#links'] = $links;
  $anchor_links['#attributes']['class'] = ['anchor-links'];
  if ($sticky) {
    $anchor_links['#attributes']['class'][] = 'sticky';
    $anchor_links['#prefix'] = '<div class="sticky-end"></div>';
    $variables['#attached']['library'][] = 'kamihaya_cms_content_type/anchor-link-sticky';
  }
  if ($full_width) {
    $variables['#attached']['html_head'][] = [
      [
        '#tag' => 'style',
        '#attributes' => [
          'type' => 'text/css',
        ],
        '#value' => 'body { overflow-x: hidden; }',
      ],
      'kamihaya_cms_content_type',
    ];
  }
}

/**
 * Create anchor links for headings Paragraphs.
 *
 * @param \Drupal\node\NodeInterface $node
 *   The node to check.
 * @param array $variables
 *   The variables to add the anchor links to.
 */
function kamihaya_cms_content_type_create_headins_anchor_link(NodeInterface $node, array &$variables) {
  $links = [];
  $anchor_links = [];

  $headings_paragraphs_fields = [];
  foreach ($node->getFields() as $field_name => $field) {
    // Check if the field is a Paragraph field.
    $field_def = $field->getFieldDefinition();
    $field_type = $field_def->getType();

    // Check if the field is an entity reference to Paragraphs.
    if ($field_type !== 'entity_reference_revisions' || $field_def->getSetting('target_type') !== 'paragraph') {
      continue;
    }
    /** @var \Drupal\Core\Field\EntityReferenceRevisionsFieldItemList $field */
    $paragraphs = $field->referencedEntities();
    if (empty($paragraphs)) {
      continue;
    }
    // Check if any of the referenced Paragraphs is of type 'headings' and has an anchor link ID.
    foreach ($paragraphs as $paragraph) {
      if ($paragraph->bundle() !== 'headings' || empty($paragraph->get('field_anchor_link_id')->value)) {
        continue;
      }
      if (empty($headings_paragraphs_fields[$field_name])) {
        $headings_paragraphs_fields[$field_name] = [];
      }
      $anchor_link_id = $paragraph->get('field_anchor_link_id')->value;
      $tag = $paragraph->get('field_title_tag')->value;
      $headings_paragraphs_fields[$field_name][$anchor_link_id] = [
        'title' => $paragraph->get('field_title_text')->value,
        'url' => Url::fromUserInput("#{$anchor_link_id}"),
        'attributes' => [
          'class' => ['anchor-link', "{$tag}_link"],
        ],
      ];
    }
  }

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

  foreach($variables['content'] as $name => &$element) {
    if (is_array($element) && array_key_exists('headings_anchor_links', $element)) {
      $anchor_links = &$element['headings_anchor_links'];
    }
    if (empty($headings_paragraphs_fields[$name]) || !is_array($element) || (isset($element['#access']) && empty($element['#access']))) {
      continue;
    }

    foreach ($headings_paragraphs_fields[$name] as $anchor_id => $link) {
      if (empty($anchor_id) || empty($link)) {
        continue;
      }

      $links[$anchor_id] = $link;
    }

  }

  if (empty($anchor_links) && !empty($variables['content']['headings_anchor_links'])) {
    $anchor_links = &$variables['content']['headings_anchor_links'];
  }
  if (empty($links) || empty($anchor_links)) {
    return;
  }
  $anchor_links['#links'] = $links;
  $anchor_links['#attributes']['class'] = ['headings-anchor-links'];
}

/**
 * Implements hook_node_load().
 */
function kamihaya_cms_content_type_node_view(array &$build, NodeInterface $node, EntityViewDisplayInterface $display, $view_mode) {
  $contents = $display->getComponents();
  foreach ($contents as $name => $field) {
    if (strpos($name, 'field_') !== 0) {
      continue;
    }
    $field_definition = $node->getFieldDefinition($name);
    if ($field_definition->getType() !== 'viewsreference' && $field_definition->getType() !== 'entity_reference') {
      continue;
    }

    $default_value = $field_definition->getDefaultValueLiteral();
    $value = $node->get($name)->getValue();
    if (count($default_value) === count($value)) {
      continue;
    }
    if (!empty($value)) {
      $default_value = array_slice($default_value, count($value));
    }
    $entity_repository = \Drupal::service('entity.repository');
    $target_id = NULL;
    foreach($default_value as $item) {
      if (empty($item) || empty($item['target_uuid']) || ($field_definition->getType() === 'viewsreference' && empty($item['display_id']))) {
        continue;
      }

      $entity_type = $field_definition->getSetting('target_type');
      if ($entity_type !== 'view' && $entity_type !== 'media') {
        continue;
      }

      $entity = $entity_repository->loadEntityByUuid($entity_type, $item['target_uuid']);
      if (empty($entity) || $entity_type === 'view' && empty($entity->getDisplay($item['display_id']))) {
        continue;
      }
      $item['target_id'] = $entity->id();
      $value[] = $item;
    }
    $node->set($name, $value);
    $build[$name] = $node->$name->view($view_mode);
  }

  if (kamihaya_cms_content_type_need_check_headings_paragraph($node)) {
    $build['headings_anchor_links'] = [
      '#theme' => 'links',
    ];
  }
  if (!in_array('anchor_links', array_keys($contents))) {
    return;
  }
  $build['anchor_links'] = [
    '#theme' => 'links',
  ];
}

/**
 * Check if the node has Paragraphs of type 'headings'.
 *
 * @param NodeInterface $node
 *   The node to check
 * @return bool
 *   TRUE if the node has Paragraphs of type 'headings', FALSE otherwise.
 */
function kamihaya_cms_content_type_need_check_headings_paragraph(NodeInterface $node) {
  foreach ($node->getFields() as $field_name => $field) {
    // Check if the field is a Paragraph field.
    $field_def = $field->getFieldDefinition();
    $field_type = $field_def->getType();

    // Check if the field is an entity reference to Paragraphs.
    if ($field_type !== 'entity_reference_revisions' || $field_def->getSetting('target_type') !== 'paragraph') {
      continue;
    }
    /** @var \Drupal\Core\Field\EntityReferenceRevisionsFieldItemList $field */
    $paragraphs = $field->referencedEntities();
    if (empty($paragraphs)) {
      continue;
    }
    // Check if any of the referenced Paragraphs is of type 'headings' and has an anchor link ID.
    foreach ($paragraphs as $paragraph) {
      if ($paragraph->bundle() === 'headings' && !empty($paragraph->get('field_anchor_link_id')->value)) {
        return TRUE;
      }
    }
  }
  return FALSE;
}

/**
 * Implements hook_entity_extra_field_info().
 */
function kamihaya_cms_content_type_entity_extra_field_info() {
  $extra = [];
  $description = t('Kamihaya cms content type module element');
  foreach (NodeType::loadMultiple() as $bundle) {
    $extra['node'][$bundle->id()]['display']['anchor_links'] = [
      'label' => t('Anchor links'),
      'description' => $description,
      'weight' => 100,
      'visible' => TRUE,
    ];

    if (!kamihaya_cms_content_type_node_with_headings_paragraph($bundle->id())) {
      continue;
    }
    $extra['node'][$bundle->id()]['display']['headings_anchor_links'] = [
      'label' => t('Anchor links(Headings)'),
      'description' => $description,
      'weight' => 100,
      'visible' => TRUE,
    ];
  }

  return $extra;
}

/**
 * Checks if a given content type has any field referencing a specific Paragraph type.
 *
 * @param string $node_bundle
 *   The machine name of the content type.
 *
 * @return bool
 *   TRUE if the content type has a field referencing the specified Paragraph type, FALSE otherwise.
 */
function kamihaya_cms_content_type_node_with_headings_paragraph(string $node_bundle) {
  // Get the entity field manager service.
  $field_manager = \Drupal::service('entity_field.manager');

  // Get all field definitions for the given content type.
  $field_definitions = $field_manager->getFieldDefinitions('node', $node_bundle);

  foreach ($field_definitions as $field_name => $field_definition) {
    // Check if the field is an entity_reference_revisions field and not a Paragraph field.
    if ($field_definition->getType() !== 'entity_reference_revisions' || $field_definition->getSetting('target_type') !== 'paragraph') {
      continue;
    }
    // Get the allowed target Paragraph bundles for this field.
    $target_bundles = $field_definition->getSetting('handler_settings')['target_bundles'] ?? [];

    // If the target Paragraph type is included, return TRUE.
    if (in_array('headings', $target_bundles, true)) {
      return TRUE;
    }
  }

  // No matching Paragraph type reference found.
  return FALSE;
}


/**
 * Implements hook_field_group_pre_render().
 */
function kamihaya_cms_content_type_field_group_pre_render(array &$element, $group, &$rendering_object) {
  if (empty($element)) {
    return;
  }

  $empty = FALSE;
  foreach($element as $name => &$field) {
    if (strpos($name, 'field_') !== 0 || empty($field['#field_type']) || $field['#field_type'] !== 'viewsreference') {
      continue;
    }
    $empty = TRUE;
    foreach($field as $key => $value) {
      if (!is_numeric($key)) {
        continue;
      }
      if (empty($value['contents']['#view'])) {
        continue;
      }
      $view = $value['contents']['#view'];
      if (empty($view->result)) {
        continue;
      }
      if ($view->style_plugin instanceof FlippedTable) {
        $render = Drupal::service('renderer')->render($value['contents']);
        if (strpos($render, '</tr>') === FALSE) {
          continue;
        }
      }
      $empty = FALSE;
    }
  }
  if ($empty) {
    $element['#access'] = FALSE;
  }

}

/**
 * Implements hook_node_load().
 */
function kamihaya_cms_content_type_node_load(array $nodes) {
  /** @var \Drupal\node\NodeInterface $node */
  foreach ($nodes as $node) {
    $field_configs = \Drupal::getContainer()->get('entity_field.manager')->getFieldDefinitions('node', $node->bundle());
    foreach ($field_configs ?: [] as $field_name => $field_config) {
      if (!empty($field_config)) {
        continue;
      }
      if (empty($field_config) || $field_config->getType() !== 'entity_reference'
        || empty($field_config->getDefaultValue($node))
        || empty($field_config->getDefaultValue($node)[0]['target_id']))  {
        continue;
      }
      if ($field_config->getSetting('handler') !== 'default:media'
        || empty($field_config->getSetting('handler_settings')['target_bundles'])
        || !in_array('image', $field_config->getSetting('handler_settings')['target_bundles'])) {
        continue;
      }
      $target_id = $field_config->getDefaultValue($node)[0]['target_id'];
      $media = \Drupal::entityTypeManager()->getStorage('media')->load($target_id);
      if (empty($media)) {
        continue;
      }
      $node->set($field_name, $media->id());
    }
  }
}

/**
 * Implements hook_entity_view_display_alter().
 */
function kamihaya_cms_content_type_form_entity_view_display_edit_form_alter(&$form, FormStateInterface $form_state) {
  $form['#process'][] = 'kamihaya_cms_content_type_entity_view_display_edit_form_process';
}

/**
 * Add Regions to 'Manage display' screen.
 *
 * @param array $form
 *   The form to add layout fieldset and extra Display Suite fields.
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 *   The current form state.
 *
 * @return array
 *   The altered form
 */
function kamihaya_cms_content_type_entity_view_display_edit_form_process(array $form, FormStateInterface $form_state) {
  if (empty($form['#fieldgroups'])) {
    return $form;
  }

  $manager = \Drupal::service('plugin.manager.field_group.formatters');
  $field_group_form_state = $form_state->get('field_group');
  if (empty($field_group_form_state)) {
    return $form;
  }
  foreach ($form['#fieldgroups'] as $field_group) {
    if (empty($form['fields'][$field_group]['format']['format_settings']['settings']) || empty($field_group_form_state[$field_group])) {
      continue;
    }

    $group = $field_group_form_state[$field_group];
    $plugin = $manager->getInstance([
      'format_type' => $group->format_type,
      'configuration' => [
        'label' => $group->label,
        'settings' => $group->format_settings,
      ],
      'group' => $group,
    ]);

    $form['fields'][$field_group]['format']['format_settings']['settings']['anchor_link_sticky'] = [
      '#type' => 'checkbox',
      '#title' => t('Sticky anchor links'),
      '#default_value' => $plugin->getSetting('anchor_link_sticky'),
    ];
  }

  return $form;

}
