<?php

declare(strict_types=1);

namespace Drupal\sobki_admin\HookHandler;

use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Template\AttributeHelper;
use Drupal\layout_builder\Form\ConfigureBlockFormBase;
use Drupal\layout_builder\Form\OverridesEntityForm;
use Drupal\layout_builder\OverridesSectionStorageInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Alter forms.
 */
class FormAlter implements ContainerInjectionInterface {

  /**
   * Place the edit template link at last position in actions.
   */
  public const EDIT_TEMPLATE_WEIGHT = 100;

  public function __construct(
    protected EntityTypeBundleInfoInterface $entityTypeBundleInfo,
  ) {}

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

  use StringTranslationTrait;

  /**
   * Alter forms.
   *
   * @param array $form
   *   The form structure.
   * @param \Drupal\Core\Form\FormStateInterface $formState
   *   The form state.
   * @param string $form_id
   *   The form ID.
   */
  public function alter(array &$form, FormStateInterface $formState, string $form_id): void {
    // Default styling for Layout Builder "main" form.
    // There is no specific form ID to target as the base form ID is dynamic in
    // LayoutBuilderEntityFormTrait.
    if (\str_ends_with($form_id, '_layout_builder_form')) {
      $this->alterLayoutBuilderForm($form, $formState);
    }
  }

  /**
   * Default styling for Layout Builder "main" form.
   *
   * @param array $form
   *   The form structure.
   * @param \Drupal\Core\Form\FormStateInterface $formState
   *   The form state.
   */
  protected function alterLayoutBuilderForm(array &$form, FormStateInterface $formState): void {
    // Close revision information by default.
    if (isset($form['revision_information'])) {
      $form['revision_information']['#open'] = FALSE;
    }

    // Hide native message.
    if (isset($form['layout_builder_message'])) {
      $form['layout_builder_message']['#access'] = FALSE;
    }

    // Add attributes on buttons to target with JS.
    if (isset($form['actions']['submit'])) {
      $form['actions']['submit']['#attributes'] = $form['actions']['submit']['#attributes'] ?? [];
      $form['actions']['submit']['#attributes'] = AttributeHelper::mergeCollections(
        // @phpstan-ignore-next-line
        $form['actions']['submit']['#attributes'],
        [
          'class' => [
            'js-layout-builder-save',
          ],
        ]
      );
    }
    if (isset($form['actions']['discard_changes'])) {
      $form['actions']['discard_changes']['#attributes'] = $form['actions']['discard_changes']['#attributes'] ?? [];
      $form['actions']['discard_changes']['#attributes'] = AttributeHelper::mergeCollections(
        // @phpstan-ignore-next-line
        $form['actions']['discard_changes']['#attributes'],
        [
          'class' => [
            'js-layout-builder-discard',
          ],
        ]
      );
    }

    // Add a link to edit template if available.
    $editTemplateLink = $this->editTemplateLink($formState);
    if (!empty($editTemplateLink)) {
      $form['actions']['edit_template'] = $editTemplateLink;
    }
  }

  /**
   * Add a link to edit template if available.
   *
   * @param \Drupal\Core\Form\FormStateInterface $formState
   *   The form state.
   *
   * @return array
   *   The edit template link render array.
   */
  protected function editTemplateLink(FormStateInterface $formState): array {
    $form_object = $formState->getFormObject();
    if (!($form_object instanceof ConfigureBlockFormBase) && !($form_object instanceof OverridesEntityForm)) {
      return [];
    }

    $sectionStorage = $form_object->getSectionStorage();
    if (!($sectionStorage instanceof OverridesSectionStorageInterface)) {
      return [];
    }
    $defaults_link = $sectionStorage
      ->getDefaultSectionStorage()
      ->getLayoutBuilderUrl();
    if (!$defaults_link->access()) {
      return [];
    }
    $entity = $sectionStorage->getContextValue('entity');
    if (!($entity instanceof EntityInterface)) {
      return [];
    }
    $entity_type = $entity->getEntityType();
    $bundle_info = $this->entityTypeBundleInfo->getBundleInfo($entity->getEntityTypeId());

    return [
      '#type' => 'link',
      '#url' => $defaults_link,
      '#title' => $entity_type->hasKey('bundle')
        ? $this->t('Edit @bundle template', ['@bundle' => $bundle_info[$entity->bundle()]['label']])
        : $this->t('Edit template'),
      '#weight' => static::EDIT_TEMPLATE_WEIGHT,
    ];
  }

}
