<?php

/**
 * @file
 * Provides a space entity type.
 */

use Drupal\Component\Utility\Html;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\nodehive_core\MenuHelperInterface;
use Drupal\nodehive_core\Plugin\views\field\EntityTranslations;
use Drupal\nodehive_core\SpaceInterface;
use Drupal\system\MenuInterface;
use Drupal\Core\Entity\EntityViewDisplayInterface;
use Drupal\node\NodeInterface;


/**
 * Implements hook_entity_base_field_info_alter().
 *
 * We have an issue where certain paragraphs can't be saved due to a missing
 * uid field, its related to the content_translation module, the paragraphs
 * module used to have the uid field but they removed it, we are adding it
 * back just to get away with the error and its not being used at all. The
 * error is located at
 * ContentTranslationMetadataWrapper::setFieldOnlyIfTranslatable().
 *
 * @todo This is a workaround, fix the underlying error.
 */
function nodehive_core_entity_base_field_info_alter(&$fields, EntityTypeInterface $entity_type) {
  if ($entity_type->id() == 'paragraph' && isset($fields['content_translation_uid'])) {
    $fields['uid'] = BaseFieldDefinition::create('entity_reference')
      ->setName('User UID')
      ->setLabel(t('User ID'));
  }
}

/**
 * Implements hook_theme().
 */
function nodehive_core_theme()
{
  return [
    'nodehive_space' => [
      'render element' => 'elements',
    ],
    'nodehive_local_settings' => [
      'variables' => [
        'base_url' => NULL,
        'space_url' => NULL,
        'space_id' => NULL,
        'language' => NULL,
        'homepage' => NULL,
      ],
    ],
    'html__webform_share_nodehive' => [
      'render element' => 'html',
    ],
  ];
}

/**
 * Implements hook_page_attachments().
 */
function nodehive_core_page_attachments(array &$attachments)
{
  $attachments['#attached']['library'][] = 'nodehive_core/global-styles';
}

/**
 * Implements hook_cron().
 */
function nodehive_core_cron()
{
  // Get the CKEditor styles URL from the module's settings.
  $config = \Drupal::configFactory()->getEditable('nodehive_core.settings');
  $ckeditor_styles_url = $config->get('ckeditor_styles_url');
  $last_css_sync_time = $config->get('ckeditor_styles_sync_time');
  $current_time = time();

  // Only run on every 3 hours.
  if ($last_css_sync_time && ($current_time - $last_css_sync_time) < 1080) {
    return;
  }

  // Check if the URL is set and valid.
  if (
    !empty($ckeditor_styles_url) &&
    Url::fromUri($ckeditor_styles_url)->isExternal()
  ) {
    $external_parser = \Drupal::service('nodehive_core.ckeditor5_external_css_parser');
    $external_parser->parseCss($ckeditor_styles_url);

    $config->set('ckeditor_styles_sync_time', time());
    $config->save();
  }
}

function nodehive_core_preprocess_breadcrumb(&$variables) {
  //dpm($variables['breadcrumb']);
  unset($variables['breadcrumb'][0]);
  unset($variables['breadcrumb'][1]);
}

/**
 * Implements hook_toolbar_alter().
 */
function nodehive_core_toolbar_alter(&$items)
{


  $items['administration']['#attached']['library'][] = 'nodehive_core/menu-styles';
  /*
  $items['administration']['tray']['toolbar_administration']['#pre_render'] = [
    [
      NodeHiveToolbar::class,
      'preRenderTray',
    ],
  ];
  */
}



function nodehive_core_module_implements_alter(&$implementations, $hook)
{
  // Move our hook to be executed last, after modules like gin_toolbar.
  /*
  if ($hook === 'toolbar_alter') {
    $value = $implementations['nodehive_core'];
    unset($implementations['nodehive_core']);
    $implementations['nodehive_core'] = $value;
  }
  */
}


/**
 * Implements hook_views_data().
 */
function nodehive_core_views_data()
{
  $data = [];

  $data['node']['nodehive_user_spaces'] = [
    'title' => t('User NodeHive spaces'),
    'help' => t("Only show content that references NodeHive spaces."),
    'filter' => [
      'title' => t('User NodeHive spaces'),
      'field' => 'nodehive_space',
      'id' => 'nodehive_user_spaces',
    ],
  ];

  return $data;
}

/**
 * Prepares variables for space templates.
 *
 * Default template: nodehive-space.html.twig.
 *
 * @param array $variables
 *   An associative array containing:
 *   - elements: An associative array containing the space information and any
 *     fields attached to the entity.
 *   - attributes: HTML attributes for the containing element.
 */
function template_preprocess_nodehive_space(array &$variables)
{
  $variables['view_mode'] = $variables['elements']['#view_mode'];
  foreach (Element::children($variables['elements']) as $key) {
    $variables['content'][$key] = $variables['elements'][$key];
  }
}



/**
 * Implements hook_css_alter().
 */
function nodehive_core_css_alter(&$css) {
  // Find tailwind.css
  $tailwind_path = 'modules/contrib/nodehive_core/css/tailwind.css';

  if (isset($css[$tailwind_path])) {
    // Set a very high weight
    $css[$tailwind_path]['weight'] = 5000;
    // Move it to the theme group
    $css[$tailwind_path]['group'] = 200; // CSS_THEME
  }
}

/**
 * Prepares variables for node templates.
 */
function nodehive_core_preprocess_node(array &$variables) {
  $config = \Drupal::config('nodehive_core.settings');
  $type = $config->get('node_preprocessor_type') ?: 'default';
  if ($type === 'multispace_iframe') {
    \Drupal::service('nodehive_core.node_preprocessor_multispace_iframe')->preprocess($variables);
  } else {
    // default
    \Drupal::service('nodehive_core.structured_content_node_preprocessor')->preprocess($variables);
  }
}

/**
 * Implements hook_library_info_alter().
 */
function nodehive_core_library_info_alter(&$libraries, $extension)
{
  unset($libraries['drupal.dialog.off_canvas']['css']['base']['misc/dialog/off-canvas/css/reset.css']);
  unset($libraries['drupal.dialog.off_canvas']['css']['base']['misc/dialog/off-canvas/css/base.css']);
  unset($libraries['drupal.dialog.off_canvas']['css']['base']['misc/dialog/off-canvas/css/utility.css']);
  unset($libraries['drupal.dialog.off_canvas']['css']['component']['misc/dialog/off-canvas/css/button.css']);
  unset($libraries['drupal.dialog.off_canvas']['css']['component']['misc/dialog/off-canvas/css/drupal.css']);
  unset($libraries['drupal.dialog.off_canvas']['css']['component']['misc/dialog/off-canvas/css/form.css']);
  unset($libraries['drupal.dialog.off_canvas']['css']['component']['misc/dialog/off-canvas/css/table.css']);
  unset($libraries['drupal.dialog.off_canvas']['css']['component']['misc/dialog/off-canvas/css/details.css']);
  unset($libraries['drupal.dialog.off_canvas']['css']['component']['misc/dialog/off-canvas/css/messages.css']);
  unset($libraries['drupal.dialog.off_canvas']['css']['component']['misc/dialog/off-canvas/css/tabledrag.css']);
  unset($libraries['drupal.dialog.off_canvas']['css']['component']['misc/dialog/off-canvas/css/throbber.css']);
  unset($libraries['drupal.dialog.off_canvas']['css']['component']['misc/dialog/off-canvas/css/dropbutton.css']);
  unset($libraries['drupal.dialog.off_canvas']['css']['component']['misc/dialog/off-canvas/css/titlebar.css']);
  unset($libraries['drupal.dialog.off_canvas']['css']['component']['misc/dialog/off-canvas/css/wrapper.css']);

  if ($extension === 'ckeditor5') {
    // Get the CKEditor styles URL from the module's settings.
    $config = \Drupal::config('nodehive_core.settings');
    $ckeditor_styles_url = $config->get('ckeditor_styles_url');

    // Check if the URL is set and valid.
    if (!empty($ckeditor_styles_url) && Url::fromUri($ckeditor_styles_url)->isExternal()) {
      $css_file = 'public://nodehive_core/ckeditor5_styles.css';

      $path = \Drupal::service('file_url_generator')
        ->generateAbsoluteString($css_file);
      $libraries['internal.drupal.ckeditor5']['css']['theme'][$path] = [
        'weight' => -100,
      ];
    }

  }
}

/**
 * Implements hook_entity_base_field_info().
 */
function nodehive_core_entity_base_field_info(EntityTypeInterface $entity_type): array
{
  $fields = [];

  if ($entity_type->id() === 'node') {
    $fields['nodehive_space'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('NodeHive Space'))
      ->setDescription(t('The space, that this content will appear on.'))
      ->setSetting('target_type', 'nodehive_space')
      ->setSetting('handler', 'default')
      ->setTargetEntityTypeId('nodehive_space')
      ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED)
      ->setDisplayOptions('form', [
        'type' => 'options_buttons',
        'weight' => 5,
        'settings' => [],
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);
  }

  return $fields;
}

/**
 * Implements hook_form_BASE_FORM_ID_alter().
 */
function nodehive_core_form_node_form_alter(&$form, FormStateInterface &$form_state, $form_id)
{
  if (!isset($form["nodehive_space"])) {
    return;
  }

  // Remove the option to select a space that doesn't allow this CT.
  $entity = $form_state->getFormObject()->getEntity();
  $type = $entity->getType();

  foreach ($form['nodehive_space']['widget']['#options'] as $id => $label) {
    $space = \Drupal::entityTypeManager()->getStorage('nodehive_space')->load($id);
    $allowed_space_ct = [];
    foreach ($space->content_types->getValue() as $item) {
      $allowed_space_ct[] = $item['target_id'];
    }

    if ($allowed_space_ct && !in_array($type, $allowed_space_ct)) {
      unset($form['nodehive_space']['widget']['#options'][$id]);
    }
  }

  // Moves the space field into sidebar on node forms.
  $form['nodehive_space_information'] = [
    '#type' => 'details',
    '#title' => t("NodeHive Spaces"),
    '#open' => TRUE,
    '#group' => 'advanced',
    '#weight' => -10,
  ];

  $form['nodehive_space_information'][] = $form['nodehive_space'];
  unset($form['nodehive_space']);
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function nodehive_core_form_menu_add_form_alter(&$form, FormStateInterface $form_state)
{
  /** @var \Drupal\nodehive_core\MenuHelperInterface $menu_helper */
  $menu_helper = \Drupal::service("nodehive_core.menu_helper");
  $menu_helper->alterMenuForm($form, $form_state);
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function nodehive_core_form_menu_edit_form_alter(&$form, FormStateInterface $form_state)
{
  /** @var \Drupal\nodehive_core\MenuHelperInterface $menu_helper */
  $menu_helper = \Drupal::service("nodehive_core.menu_helper");
  $menu_helper->alterMenuForm($form, $form_state);
}

/**
 * Implements hook_entity_type_alter().
 */
function nodehive_core_entity_type_alter(array &$entity_types)
{
  /** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */
  $entity_types['menu']->setListBuilderClass('Drupal\nodehive_core\MenuListBuilder');
}

/**
 * Implements hook_field_widget_complete_form_alter().
 */
function nodehive_core_field_widget_complete_form_alter(&$field_widget_complete_form, FormStateInterface $form_state, $context)
{
  $field_name = $field_widget_complete_form['widget']['#field_name'];
  if ($field_name != "nodehive_space") {
    return;
  }

  if (in_array("administrator", \Drupal::currentUser()->getRoles()) || \Drupal::currentUser()->id() === 1) {
    return;
  }

  foreach ($field_widget_complete_form['widget'] as $key => $field) {
    if (str_starts_with($key, '#')) {
      continue;
    }

    $target_id = $field['target_id'];
    if (!isset($target_id['#default_value'])) {
      continue;
    }

    $space = $target_id['#default_value'];

    $has_user_access = FALSE;
    $editors = $space->editors->referencedEntities();
    foreach ($editors as $editor) {
      if ($editor->id() == \Drupal::currentUser()->id()) {
        $has_user_access = TRUE;
      }
    }

    if (!$has_user_access) {
      $field_widget_complete_form['widget'][$key]['target_id']['#attributes']['disabled'] = TRUE;
    }
  }
}

/**
 * Implements hook_form_alter().
 */
function nodehive_core_form_alter(&$form, FormStateInterface $form_state, $form_id): void
{
  $form_ids = [
    "user_register_form",
    "user_form",
  ];

  if (!in_array($form_id, $form_ids)) {
    return;
  }

  $current_user_roles = \Drupal::currentUser()->getRoles();
  $allowed_roles = [
    "administrator",
    "nodehive-admin"
  ];

  if (empty(array_intersect($current_user_roles, $allowed_roles)) && \Drupal::currentUser()->id() != 1) {
    return;
  }

  /** @var \Drupal\user\UserInterface $user */
  $user = $form_state->getFormObject()->getEntity();
  $spaces = \Drupal::entityTypeManager()
    ->getStorage('nodehive_space')
    ->loadMultiple();

  $default_value = [];
  $spaces_options = [];
  foreach ($spaces as $space) {
    $spaces_options[$space->id()] = $space->label();

    if ($form_id == 'user_form') {
      foreach ($space->editors->getValue() as $item) {
        if ($item['target_id'] == $user->id()) {
          $default_value[] = $space->id();
        }
      }
    }
  }

  $form['spaces'] = [
    '#type' => 'checkboxes',
    '#title' => t('Spaces'),
    '#options' => $spaces_options,
    '#default_value' => $default_value,
    '#weight' => -2,
  ];

  $form['actions']['submit']['#submit'][] = "_nodehive_core_user_form_submit";
}

/**
 * Custom submit handler for user forms.
 *
 * @param array $form
 *   Render array.
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 *   Current form state.
 */
function _nodehive_core_user_form_submit(&$form, FormStateInterface $form_state): void
{
  $spaces = $form_state->getValue('spaces');

  /** @var \Drupal\user\UserInterface $user */
  $user = $form_state->getFormObject()->getEntity();

  foreach ($spaces as $space_id => $is_set) {
    /** @var \Drupal\nodehive_core\SpaceInterface $space */
    $space = \Drupal::entityTypeManager()
      ->getStorage('nodehive_space')
      ->load($space_id);

    // Check if we already have this user set.
    $new_value = [];
    foreach ($space->editors->getValue() as $item) {
      if (!$is_set && $item['target_id'] == $user->id()) {
        continue;
      }
      $new_value[] = $item['target_id'];
    }

    if ($is_set && !in_array($user->id(), $new_value)) {
      $new_value[] = $user->id();
    }

    $space->editors = $new_value;
    $space->save();
  }
}

/**
 * Implements hook_entity_insert().
 *
 * Adds two-way reference, one on the entity that contains the
 * space reference field and directly a reference to a node inside a
 * space entity.
 */
function nodehive_core_node_insert(EntityInterface $entity): void
{
  $entityFieldManager = \Drupal::service('entity_field.manager');
  $fields = $entityFieldManager->getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle());

  if (!in_array("nodehive_space", array_keys($fields))) {
    return;
  }

  $referenced_space = $entity->get('nodehive_space')->referencedEntities();
  if (!$referenced_space) {
    return;
  }

  foreach ($referenced_space as $ref_space) {
    if (!$ref_space instanceof SpaceInterface) {
      continue;
    }

    $content_ids = $ref_space->content->getValue();
    $content_ids[] = ['target_id' => $entity->id()];
    $ref_space->set("content", $content_ids);
    $ref_space->save();
  }
}

/**
 * Implements hook_entity_update().
 */
function nodehive_core_node_update(EntityInterface $entity): void
{
  $entityFieldManager = \Drupal::service('entity_field.manager');
  $fields = $entityFieldManager->getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle());

  if (!in_array("nodehive_space", array_keys($fields))) {
    return;
  }

  $org_referenced_space = [];
  $org_referenced_space_values = $entity->original
    ->get('nodehive_space')
    ->getValue();

  foreach ($org_referenced_space_values as $val) {
    $org_referenced_space[] = $val['target_id'];
  }

  $referenced_space = [];
  $referenced_space_values = $entity->get('nodehive_space')->getValue();
  foreach ($referenced_space_values as $val) {
    $referenced_space[] = $val['target_id'];
  }

  $removed_spaces = array_diff($org_referenced_space, $referenced_space);
  $added_spaces = array_diff($referenced_space, $org_referenced_space);

  if ($removed_spaces) {
    foreach ($removed_spaces as $space_id) {
      $space = \Drupal::entityTypeManager()
        ->getStorage("nodehive_space")
        ->load($space_id);

      if (!$space) {
        continue;
      }

      $content_ids = $space->content->getValue();
      foreach ($content_ids as $key => $item) {
        if ($item['target_id'] === $entity->id()) {
          unset($content_ids[$key]);
        }
      }

      $space->set("content", $content_ids);
      $space->save();
    }
  }

  if ($added_spaces) {
    foreach ($added_spaces as $space_id) {
      $space = \Drupal::entityTypeManager()
        ->getStorage("nodehive_space")
        ->load($space_id);

      if (!$space) {
        continue;
      }

      $content_ids = $space->content->getValue();
      $content_ids[] = ['target_id' => $entity->id()];
      $space->set("content", $content_ids);
      $space->save();
    }
  }
}

/**
 * Implements hook_entity_delete().
 */
function nodehive_core_node_delete(EntityInterface $entity): void
{
  $entityFieldManager = \Drupal::service('entity_field.manager');
  $fields = $entityFieldManager->getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle());

  if (!in_array("nodehive_space", array_keys($fields))) {
    return;
  }

  $referenced_space = $entity->get('nodehive_space')->referencedEntities();
  if (!$referenced_space) {
    return;
  }

  foreach ($referenced_space as $space) {
    if (!$space instanceof SpaceInterface) {
      continue;
    }

    $content_ids = $space->content->getValue();
    foreach ($content_ids as $key => $item) {
      if ($item['target_id'] === $entity->id()) {
        unset($content_ids[$key]);
      }
    }

    $space->set("content", $content_ids);
    $space->save();
  }
}

/**
 * Implements hook_entity_delete().
 */
function nodehive_core_node_type_delete(EntityInterface $entity): void {
  $spaces = \Drupal::entityTypeManager()->getStorage("nodehive_space")
    ->loadByProperties([
      "content_types" => [$entity->id()],
    ]);

  /** @var \Drupal\nodehive_core\SpaceInterface $space */
  foreach ($spaces as $space) {
    $content_types = $space->content_types->getValue();
    foreach ($content_types as $key => $item) {
      if ($item['target_id'] === $entity->id()) {
        unset($content_types[$key]);
      }
    }

    $space->set("content_types", $content_types);
    $space->save();
  }
}

/**
 * Implements hook_ENTITY_TYPE_access().
 */
function nodehive_core_menu_access(MenuInterface $menu, $operation, AccountInterface $account)
{
  if (in_array("administrator", $account->getRoles()) || $account->id() == 1) {
    return AccessResult::allowed();
  }

  switch ($operation) {
    case "update":
    case "delete":
      if (in_array($menu->id(), MenuHelperInterface::ADMIN_MENUS)) {
        return AccessResult::forbidden();
      }

      return AccessResult::neutral();
  }

  return AccessResult::neutral();
}

/**
 * Implements hook_preprocess_menu().
 *
 * This is "hacky" way to dynamically render menu items inside the
 * Nodehive menus.
 */
function nodehive_core_preprocess_menu(&$vars)
{
  $menu_name = $vars['menu_name'];
  if (!in_array($menu_name, ["nodehive-administrator", "nodehive-editor"])) {
    return;
  }

  $currentUser = \Drupal::currentUser();
  if (in_array("administrator", $currentUser->getRoles()) || $currentUser->id() == 1) {
    return;
  }

  $spaces = \Drupal::entityTypeManager()
    ->getStorage('nodehive_space')
    ->loadByProperties([
      "editors" => $currentUser->id(),
    ]);
  $spaces = array_keys($spaces);

  foreach ($vars['items'] as $key => $link) {
    $title = $link['title'];
    if ($title != "Spaces") {
      continue;
    }

    $children = $link['below'];

    foreach ($children as $ckey => $child) {
      /** @var \Drupal\Core\Url $url */
      $url = $child['url'];
      $params = $url->getRouteParameters();

      if (!isset($params['nodehive_space'])) {
        continue;
      }

      if (!in_array($params['nodehive_space'], $spaces)) {
        unset($children[$ckey]);
      }
    }

    $vars['items'][$key]['below'] = $children;
  }
}

/**
 * Implements hook_views_data_alter().
 */
function nodehive_core_views_data_alter(array &$data)
{
  // Registers an entity area handler per entity type.
  foreach (Drupal::service('entity_type.manager')->getDefinitions() as $entity_info) {
    $data[$entity_info->getBaseTable()]['translation_button'] = [
      'title' => 'Nodehive Entity translations field',
      'help' => t('Displays all available translations and a quick way for adding the unexisting ones.'),
      'field' => [
        'id' => 'nodehive_core_entity_translations',
      ],
    ];
  }
}



/**
 * A list of allowed values for "Space Type".
 *
 * @param \Drupal\Core\Field\BaseFieldDefinition $definition
 *   Storage definition.
 * @param \Drupal\Core\Entity\ContentEntityInterface $entity
 *   Entity.
 * @param bool $cacheable
 *   Is cacheable.
 */
function nodehive_core_space_type_allowed_values(BaseFieldDefinition $definition, ContentEntityInterface $entity = NULL, $cacheable)
{
  $options = [
    "full_website" => t("Website"),
    "directory" => t("Website Subdirectory"),
    "database" => t("Database (no frontend)"),
    "other" => t("Other"),
  ];

  return $options;
}

/**
 * Implements hook_menu_local_actions_alter().
 */
function nodehive_core_menu_local_actions_alter(&$local_actions)
{
  // Add the destination param.
  if (isset($local_actions['nodehive_core.add_user'])) {
    $local_actions['nodehive_core.add_user']['options']['query'] = [
      'destination' => "/nodehive/users"
    ];
  }
}

/**
 * Custom function to copy static assets.
 */
function _nodehive_core_copy_static_assets()
{

  // Files to import
  $files = [
    "/images/nodehive_logo_teal.png" => 'public://nodehive_logo_teal.png',
    "/images/nodehive_logo_black.png" => 'public://nodehive_logo_black.png',
    "/images/nodehive_login_screen.png" => 'public://nodehive_login_screen.png'
  ];

  foreach ($files as $source_path => $destination) {
    $source = \Drupal::service('extension.list.module')
      ->getPath('nodehive_core') . $source_path;

    if (!file_exists($destination)) {
      // Copy the file.
      $file = \Drupal::service('file_system')->copy(
        $source,
        $destination,
        FileSystemInterface::EXISTS_REPLACE
      );

      if (!$file) {
        \Drupal::messenger()->addError(
          t(
            'The file could not be copied to the public directory.'
          )
        );
      }
    }
  }
}

/**
 * Provide custom template for CSS that can be loaded from the frontend.
 */
function nodehive_core_theme_suggestions_html_alter(array &$suggestions, array $variables) {
  /** @var \Drupal\webform\WebformInterface $webform */
  $route = \Drupal::routeMatch()->getRouteName();
  $moduleHandler = \Drupal::service('module_handler');

  if ($route !== 'entity.webform.share_page.javascript'
    || !$moduleHandler->moduleExists('webform_share')) {
    return;
  }

  $suggestions[] = 'html__webform_share_nodehive';
}

/**
 * Prepares variables for the webform share page HTML templates.
 */
function template_preprocess_html__webform_share_nodehive(&$variables) {
  $moduleHandler = \Drupal::service('module_handler');
  if (!$moduleHandler->moduleExists('webform_share')) {
    return;
  }

  $webform_styles_url = \Drupal::config('nodehive_core.settings')
    ->get('webform_styles_url');
  $variables['webform_css_path'] = $webform_styles_url;

  // Run preprocess hook from the webform_share.module.
  template_preprocess_html__webform_share($variables);
}

/**
 * Implements hook_entity_extra_field_info().
 */
function nodehive_core_entity_extra_field_info() {
  $extra = [];

  // Add our custom field to all node types
  foreach (\Drupal::entityTypeManager()->getStorage('node_type')->loadMultiple() as $bundle) {
    $extra['node'][$bundle->id()]['display']['spaces_iframe'] = [
      'label' => t('Spaces Iframe'),
      'description' => t('Displays content in an iframe.'),
      'weight' => 100,
      'visible' => TRUE,
    ];
  }

  return $extra;
}

/**
 * Implements hook_entity_view().
 */
function nodehive_core_entity_view(array &$build, EntityInterface $entity, \Drupal\Core\Entity\Entity\EntityViewDisplay $display, $view_mode) {
  if ($entity instanceof NodeInterface && $display->getComponent('spaces_iframe')) {
    // Get all spaces this node is attached to
    $spaces = $entity->get('nodehive_space')->referencedEntities();

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

    // Generate JWT token once for all spaces
    $jwt_token = \Drupal::service('jwt.authentication.jwt')->generateToken();
    $iframe_origins = [];

    // First pass: collect iframe origins
    foreach ($spaces as $index => $space) {
      $space_id = $space->id();
      $tab_id = 'space-tab-' . $space_id . '-' . $entity->id();
      $space_url = $space->get('space_url')->getString();

      if (!empty($space_url)) {
        $iframe_origins[$tab_id] = $space_url;
      }
    }

    // Create tabs container
    $build['spaces_iframe'] = [
      '#type' => 'container',
      '#attributes' => [
        'class' => ['spaces-iframe-tabs', 'h-full', 'flex', 'flex-col'],
        'id' => 'spaces-iframe-tabs-' . $entity->id(),
      ],
      '#attached' => [
        'library' => ['nodehive_core/spaces-iframe'],
        'drupalSettings' => [
          'nodehive_core' => [
            'spaces_iframe' => [
              'jwt_token' => $jwt_token,
              'iframe_origins' => $iframe_origins,
            ],
          ],
        ],
      ],
      '#weight' => $display->getComponent('spaces_iframe')['weight'],
    ];

    // Add tab navigation
    $build['spaces_iframe']['tabs'] = [
      '#type' => 'container',
      '#attributes' => [
        'class' => ['spaces-iframe-tabs-nav', 'flex-shrink-0'],
        'role' => 'tablist',
      ],
    ];

    // Add tab content container
    $build['spaces_iframe']['content'] = [
      '#type' => 'container',
      '#attributes' => [
        'class' => ['spaces-iframe-tabs-content', 'flex-grow', 'h-full'],
      ],
    ];

    // Add a tab for each space
    foreach ($spaces as $index => $space) {
      $space_id = $space->id();
      $tab_id = 'space-tab-' . $space_id . '-' . $entity->id();
      $space_url = $space->get('space_url')->getString();

      if (empty($space_url)) {
        continue;
      }

      $current_language = \Drupal::languageManager()->getCurrentLanguage()->getId();
      $preview_url = $space_url . '/' . $current_language . '/node/' . $entity->id();

      // Add tab button
      $build['spaces_iframe']['tabs'][$tab_id] = [
        '#type' => 'html_tag',
        '#tag' => 'button',
        '#attributes' => [
          'class' => ['spaces-iframe-tab-button'],
          'data-tab' => $tab_id,
          'aria-selected' => $index === 0 ? 'true' : 'false',
          'role' => 'tab',
          'aria-controls' => $tab_id,
          'id' => 'tab-' . $tab_id,
        ],
        '#value' => $space->label(),
      ];

      // Add tab content with iframe
      $build['spaces_iframe']['content'][$tab_id] = [
        '#type' => 'container',
        '#attributes' => [
          'class' => ['spaces-iframe-tab-content', 'h-full'],
          'id' => $tab_id,
          'aria-hidden' => $index === 0 ? 'false' : 'true',
          'style' => $index === 0 ? '' : 'display: none;',
          'role' => 'tabpanel',
          'aria-labelledby' => 'tab-' . $tab_id,
        ],
        'iframe' => [
          '#type' => 'html_tag',
          '#tag' => 'iframe',
          '#attributes' => [
            'src' => $preview_url,
            'width' => '100%',
            'height' => '1000',
            'frameborder' => '0',
            'style' => 'min-height: 100%;',
            'class' => ['spaces-iframe'],
            'data-tab-id' => $tab_id,
          ],
        ],
      ];
    }
  }
}
