<?php

declare(strict_types=1);

namespace Drupal\nodehive_taxonomy\Hook;

use Drupal\Core\Entity\EntityFormInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\taxonomy\VocabularyInterface;

/**
 * Adds a NodeHive Space field toggle to taxonomy vocabulary edit forms.
 */
final class TaxonomyVocabularyFormHooks {

  use StringTranslationTrait;

  /**
   * The field_config entity storage.
   *
   * @var \Drupal\Core\Entity\EntityStorageInterface
   */
  private EntityStorageInterface $fieldConfigStorage;

  /**
   * The field_storage_config entity storage.
   *
   * @var \Drupal\Core\Entity\EntityStorageInterface
   */
  private EntityStorageInterface $fieldStorageConfigStorage;

  /**
   * The entity_form_display entity storage.
   *
   * @var \Drupal\Core\Entity\EntityStorageInterface
   */
  private EntityStorageInterface $formDisplayStorage;

  /**
   * Constructs a TaxonomyVocabularyFormHooks instance.
   */
  public function __construct(
    private readonly EntityTypeManagerInterface $entityTypeManager,
  ) {
    $this->fieldConfigStorage = $entityTypeManager->getStorage('field_config');
    $this->fieldStorageConfigStorage = $entityTypeManager->getStorage('field_storage_config');
    $this->formDisplayStorage = $entityTypeManager->getStorage('entity_form_display');
  }

  /**
   * Alters the taxonomy vocabulary form to add NodeHive Space field toggle.
   */
  public function formTaxonomyVocabularyFormAlter(array &$form, FormStateInterface $form_state, string $form_id): void {
    $formObject = $form_state->getFormObject();
    if (!$formObject instanceof EntityFormInterface) {
      return;
    }

    $vocabulary = $formObject->getEntity();
    if (!$vocabulary instanceof VocabularyInterface || $vocabulary->isNew()) {
      return;
    }

    $vid = $vocabulary->id();
    $fieldExists = $this->fieldConfigStorage
      ->load("taxonomy_term.{$vid}.nodehive_space") !== NULL;

    $form['nodehive'] = [
      '#type' => 'details',
      '#title' => $this->t('NodeHive'),
      '#open' => TRUE,
    ];

    $form['nodehive']['nodehive_space_enabled'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Enable NodeHive Space field'),
      '#description' => $this->t('Adds a NodeHive Space reference field to terms in this vocabulary. When enabled, selecting a space will be required when creating or editing terms.'),
      '#default_value' => (int) $fieldExists,
    ];

    $form['actions']['submit']['#submit'][] = [$this, 'submitNodehiveSpaceField'];
  }

  /**
   * Submit handler to create or delete the NodeHive Space field.
   */
  public function submitNodehiveSpaceField(array &$form, FormStateInterface $form_state): void {
    $formObject = $form_state->getFormObject();
    if (!$formObject instanceof EntityFormInterface) {
      return;
    }

    $vocabulary = $formObject->getEntity();
    if (!$vocabulary instanceof VocabularyInterface) {
      return;
    }

    $vid = $vocabulary->id();
    $enabled = (bool) $form_state->getValue('nodehive_space_enabled');
    $fieldExists = $this->fieldConfigStorage
      ->load("taxonomy_term.{$vid}.nodehive_space") !== NULL;

    if ($enabled && !$fieldExists) {
      $this->createNodehiveSpaceField($vid);
    }
    elseif (!$enabled && $fieldExists) {
      $this->deleteNodehiveSpaceField($vid);
    }
  }

  /**
   * Creates the NodeHive Space field storage and instance for the vocabulary.
   */
  private function createNodehiveSpaceField(string $vid): void {
    $storage = $this->fieldStorageConfigStorage
      ->load('taxonomy_term.nodehive_space');
    if (!$storage) {
      $storage = $this->fieldStorageConfigStorage->create([
        'field_name' => 'nodehive_space',
        'entity_type' => 'taxonomy_term',
        'type' => 'entity_reference',
        'settings' => [
          'target_type' => 'nodehive_space',
        ],
        'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
      ]);
      $storage->save();
    }

    $this->fieldConfigStorage->create([
      'field_storage' => $storage,
      'bundle' => $vid,
      'label' => 'NodeHive Space',
      'settings' => [
        'handler' => 'default',
      ],
    ])->save();

    /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface|null $formDisplay */
    $formDisplay = $this->formDisplayStorage
      ->load("taxonomy_term.{$vid}.default");
    if ($formDisplay) {
      $formDisplay->setComponent('nodehive_space', [
        'type' => 'options_buttons',
        'weight' => 100,
      ]);
      $formDisplay->save();
    }
  }

  /**
   * Deletes the NodeHive Space field instance and storage for the vocabulary.
   */
  private function deleteNodehiveSpaceField(string $vid): void {
    $field = $this->fieldConfigStorage
      ->load("taxonomy_term.{$vid}.nodehive_space");
    $field?->delete();

    $storage = $this->fieldStorageConfigStorage
      ->load('taxonomy_term.nodehive_space');
    if ($storage !== NULL && empty($storage->getBundles())) {
      $storage->delete();
    }
  }

}
