<?php

namespace Drupal\nodehive_public_api\Controller;

use Drupal\Core\Cache\CacheableJsonResponse;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\nodehive_core\MenuHelperInterface;
use Drupal\nodehive_public_api\ApiResponseTrait;
use Drupal\nodehive_public_api\Service\MenuTreeBuilderService;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Controller for menu API endpoints.
 */
class MenuApiController extends ControllerBase {

  use ApiResponseTrait;

  /**
   * The menu tree builder service.
   *
   * @var \Drupal\nodehive_public_api\Service\MenuTreeBuilderService
   */
  protected $menuTreeBuilder;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The language manager.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $languageManager;

  /**
   * Constructs a MenuApiController object.
   *
   * @param \Drupal\nodehive_public_api\Service\MenuTreeBuilderService $menu_tree_builder
   *   The menu tree builder service.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
   *   The language manager.
   */
  public function __construct(
    MenuTreeBuilderService $menu_tree_builder,
    EntityTypeManagerInterface $entity_type_manager,
    LanguageManagerInterface $language_manager,
  ) {
    $this->menuTreeBuilder = $menu_tree_builder;
    $this->entityTypeManager = $entity_type_manager;
    $this->languageManager = $language_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('nodehive_public_api.menu_tree_builder'),
      $container->get('entity_type.manager'),
      $container->get('language_manager')
    );
  }

  /**
   * Returns the menu tree for a given menu.
   *
   * @param string $menu_id
   *   The menu ID.
   *
   * @return \Drupal\Core\Cache\CacheableJsonResponse
   *   The JSON response containing the menu tree.
   */
  public function getMenu(string $menu_id): CacheableJsonResponse {
    // Check if menu is excluded.
    if (in_array($menu_id, MenuHelperInterface::API_EXCLUDED_MENUS)) {
      $this->getLogger('nodehive_public_api')->warning(
        'Attempted access to excluded menu @menu_id via API.',
        ['@menu_id' => $menu_id]
      );
      return $this->apiError(
        (string) $this->t('Menu @menu_id is not available via this API.', ['@menu_id' => $menu_id]),
        403
      );
    }

    // Get the current language from the language manager.
    $current_language = $this->languageManager->getCurrentLanguage();
    $language = $current_language->getId();

    // Validate the menu exists.
    $menu_storage = $this->entityTypeManager->getStorage('menu');
    $menu = $menu_storage->load($menu_id);

    if (!$menu) {
      $this->getLogger('nodehive_public_api')->notice(
        'Menu @menu_id not found.',
        ['@menu_id' => $menu_id]
      );
      return $this->apiError(
        (string) $this->t('Menu @menu_id not found.', ['@menu_id' => $menu_id]),
        404
      );
    }

    // Build the menu tree.
    try {
      $menu_tree = $this->menuTreeBuilder->buildMenuTree($menu_id, $language);
    }
    catch (\Exception $e) {
      $this->getLogger('nodehive_public_api')->error(
        'Error building menu tree for @menu_id: @message',
        ['@menu_id' => $menu_id, '@message' => $e->getMessage()]
      );
      return $this->apiError(
        (string) $this->t('An error occurred while building the menu tree.'),
        500
      );
    }

    // Create response with cache metadata.
    $cache_metadata = new CacheableMetadata();
    $cache_metadata->addCacheContexts(['user.permissions', 'languages:language_interface']);
    $cache_metadata->addCacheTags(['config:system.menu.' . $menu_id]);

    $response = $this->apiSuccess([
      'menu_id' => $menu_id,
      'language' => $language,
      'items' => $menu_tree,
    ], $cache_metadata);

    $response->addCacheableDependency($menu);

    return $response;
  }

}
