<?php

declare(strict_types=1);

namespace Drupal\sobki_admin\Form;

use Drupal\Component\Transliteration\TransliterationInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\sobki_admin\Service\LayoutContextHelperInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Defines a class for reacting to form operations.
 */
class FormOperations implements ContainerInjectionInterface {

  use StringTranslationTrait;

  /**
   * The renderer service.
   *
   * @var \Drupal\Core\Render\RendererInterface
   */
  protected RendererInterface $renderer;

  /**
   * The entity type bundle info service.
   *
   * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
   */
  protected EntityTypeBundleInfoInterface $entityTypeBundleInfo;

  /**
   * The layout context helper.
   *
   * @var \Drupal\sobki_admin\Service\LayoutContextHelperInterface
   */
  protected LayoutContextHelperInterface $layoutContextHelper;

  /**
   * The transliteration service.
   *
   * @var \Drupal\Component\Transliteration\TransliterationInterface
   */
  protected TransliterationInterface $transliteration;

  /**
   * A list of UI Styles wrappers to be processed before render.
   *
   * @var string[]
   */
  private array $uiStylesElements;

  /**
   * Constructor.
   *
   * @param \Drupal\Core\Render\RendererInterface $renderer
   *   The renderer service.
   * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entityTypeBundleInfo
   *   The entity type bundle info service.
   * @param \Drupal\sobki_admin\Service\LayoutContextHelperInterface $layoutContextHelper
   *   The layout context helper.
   * @param \Drupal\Component\Transliteration\TransliterationInterface $transliteration
   *   The transliteration service.
   */
  public function __construct(
    RendererInterface $renderer,
    EntityTypeBundleInfoInterface $entityTypeBundleInfo,
    LayoutContextHelperInterface $layoutContextHelper,
    TransliterationInterface $transliteration,
  ) {
    $this->renderer = $renderer;
    $this->entityTypeBundleInfo = $entityTypeBundleInfo;
    $this->layoutContextHelper = $layoutContextHelper;
    $this->transliteration = $transliteration;

    $this->uiStylesElements = [
      'ui_styles_wrapper',
      'ui_styles_title',
      'ui_styles',
    ];
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container): static {
    return new static(
      $container->get('renderer'),
      $container->get('entity_type.bundle.info'),
      $container->get('sobki_admin.layout_context_helper'),
      $container->get('transliteration'),
    );
  }

  /**
   * Alters forms for our Sobki customizations.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   * @param string $form_id
   *   The form ID.
   *
   * @see hook_form_alter()
   */
  public function formAlter(array &$form, FormStateInterface $form_state, string $form_id): void {
    // layout_builder_configure_section.
    // layout_builder_add_block.
    if ($form_id === 'layout_builder_add_block' || $form_id === 'layout_builder_update_block') {
      // Primary tabs.
      $form['sobki_primary_tabs'] = [
        '#theme' => 'item_list',
        '#list_type' => 'ul',
        '#items' => [
          $this->getListElement('Content', 'sobki-primary-tab-content', 'sobki-primary-tab', 'active'),
          $this->getListElement('Styles', 'sobki-primary-tab-styles', 'sobki-primary-tab'),
        ],
        '#attributes' => [
          'class' => [
            'sobki-tab',
            'sobki-primary-tab',
            'nav',
            'nav-pills',
            'glb-claro-details__wrapper',
          ],
        ],
        '#weight' => (int) -99,
      ];

      // Secondary tabs.
      $secondary_tabs = [
        '#theme' => 'item_list',
        '#list_type' => 'ul',
        '#items' => [
          $this->getListElement('Block', 'sobki-secondary-tab-block', 'sobki-secondary-tab', 'active'),
          $this->getListElement('Title', 'sobki-secondary-tab-title', 'sobki-secondary-tab'),
          $this->getListElement('Inner content', 'sobki-secondary-tab-content', 'sobki-secondary-tab'),
        ],
        '#attributes' => [
          'class' => [
            'sobki-tab',
            'sobki-secondary-tab',
            'nav',
            'glb-claro-details__wrapper',
          ],
          'data-drupal-selector' => [
            'edit-sobki-primary-tabs',
          ],
        ],
      ];

      // Wrappers & script attachment.
      $form['settings']['#prefix'] = '<div id="sobki-primary-tab-content" class="sobki-primary-tab-wrapper">';
      $form['settings']['#suffix'] = '</div>';
      $form['ui_styles_wrapper']['#prefix'] = '<div id="sobki-primary-tab-styles" class="sobki-primary-tab-wrapper">' . $this->renderer->render($secondary_tabs) . '<div id="sobki-secondary-tab-block" class="sobki-secondary-tab-wrapper">';
      $form['ui_styles_wrapper']['#suffix'] = '</div>';
      $form['ui_styles_title']['#prefix'] = '<div id="sobki-secondary-tab-title" class="sobki-secondary-tab-wrapper">';
      $form['ui_styles_title']['#suffix'] = '</div>';
      $form['ui_styles']['#prefix'] = '<div id="sobki-secondary-tab-content" class="sobki-secondary-tab-wrapper">';
      $form['ui_styles']['#suffix'] = '</div></div>';
      $form['#attached']['library'][] = 'sobki_admin/sobki_admin_tabs';

      // Force open all UI Styles fieldsets as there are the tabs for that.
      foreach ($this->uiStylesElements as $element) {
        $form[$element]['#type'] = 'container';
      }

      // Add a separator between "block title" section and "block content"
      // section.
      if (isset($form['settings']['label_display'])) {
        $form['settings']['label_display']['#suffix'] = '<hr>';
      }
    }

    if ($form_id === 'node_page_layout_builder_form' || $form_id === 'entity_view_display_layout_builder_form') {
      /** @var \Drupal\layout_builder\Form\UpdateBlockForm $form_object */
      $form_object = $form_state->getFormObject();
      $contexts = $form_object->getSectionStorage();
      $plugin_id = $contexts->getPluginId();

      /** @var string $entity_type_id */
      $entity_type_id = $this->layoutContextHelper->getHostEntityTypeId($contexts);
      $entity_bundle_id = $this->layoutContextHelper->getHostEntityBundle($contexts);

      $bundle_label = $this->entityTypeBundleInfo
        ->getBundleInfo($entity_type_id)[$entity_bundle_id]['label'];

      $tab_items = [];
      $tab_items[] = [
        '#markup' => '<div class="nav-link"><b>' . $bundle_label . '</b></div>',
        '#wrapper_attributes' => [
          'class' => [
            'nav-item',
          ],
        ],
      ];
      if ($entity_type_id == 'node') {
        $layout_url = Url::fromRoute('layout_builder.defaults.' . $entity_type_id . '.view')
          ->setRouteParameters([
            'node_type' => $entity_bundle_id,
            'view_mode_name' => 'full',
          ]);
        $layout_link = Link::fromTextAndUrl($this->t('Manage template'), $layout_url)->toString();

        if ($plugin_id === 'overrides') {
          $tab_items[] = [
            '#markup' => '<div class="nav-link active">' . $this->t('Content') . '</div>',
            '#wrapper_attributes' => [
              'class' => [
                'nav-item',
                'active',
              ],
            ],
          ];
          $tab_items[] = [
            '#markup' => '<div class="nav-link">' . $layout_link . '</div>',
            '#wrapper_attributes' => [
              'class' => [
                'nav-item',
              ],
            ],
          ];
        }
        else {
          $tab_items[] = [
            '#markup' => '<div class="nav-link active">' . $this->t('Template') . '</div>',
            '#wrapper_attributes' => [
              'class' => [
                'nav-item',
                'active',
              ],
            ],
          ];
        }
      }

      // Primary tabs.
      $form['sobki_primary_tabs'] = [
        '#theme' => 'item_list',
        '#list_type' => 'ul',
        '#items' => $tab_items,
        '#attributes' => [
          'class' => [
            'nav',
            'nav-pills',
            'glb-claro-details__wrapper',
          ],
        ],
        '#weight' => (int) -9999,
      ];

      $form['revision_information']['#open'] = FALSE;
      unset($form['layout_builder_message']);
    }
  }

  /**
   * Formats a proper item list array for usage in the render array.
   *
   * @param string $title
   *   The link title.
   * @param string $fragment
   *   The anchor on which the link points.
   * @param string $class
   *   A CSS class.
   * @param string $active
   *   Active class to apply to the element.
   *
   * @return array
   *   The list element.
   */
  private function getListElement(string $title, string $fragment, string $class, string $active = ''): array {
    $url = Url::fromRoute('<none>')->setOptions([
      'fragment' => $fragment,
      'attributes' => [
        'id' => 'link-' . $fragment,
        'class' => [
          'nav-link',
          $class,
          $active,
        ],
      ],
    ]);
    // phpcs:ignore Drupal.Semantics.FunctionT.NotLiteralString
    $link = Link::fromTextAndUrl($this->t($title), $url)->toString();
    return [
      '#markup' => $link,
      '#wrapper_attributes' => [
        'class' => [
          'nav-item',
        ],
      ],
    ];
  }

}
