<?php

namespace Drupal\eb_ui\Service;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;

/**
 * Manages grid provider discovery and selection.
 *
 * This service discovers grid providers via hook_eb_ui_grid_provider_info()
 * and determines which provider is active based on eb_ui.settings.
 */
class GridProviderManager implements GridProviderManagerInterface {

  /**
   * Cached provider list.
   *
   * @var array<string, array<string, mixed>>|null
   */
  protected ?array $providers = NULL;

  /**
   * Constructor.
   *
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler
   *   The module handler for invoking hooks.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
   *   The config factory for reading settings.
   */
  public function __construct(
    protected ModuleHandlerInterface $moduleHandler,
    protected ConfigFactoryInterface $configFactory,
  ) {}

  /**
   * {@inheritdoc}
   */
  public function getAvailableProviders(): array {
    if ($this->providers !== NULL) {
      return $this->providers;
    }

    $this->providers = [];

    // Invoke hook to discover all grid providers.
    $providers = $this->moduleHandler->invokeAll('eb_ui_grid_provider_info');

    // Validate and normalize provider definitions.
    foreach ($providers as $id => $provider) {
      if (!isset($provider['id'])) {
        $provider['id'] = $id;
      }

      // Ensure required fields exist.
      if (!isset($provider['label'], $provider['form_class'])) {
        continue;
      }

      $this->providers[$id] = $provider + [
        'library' => NULL,
        'theme_class' => NULL,
      ];
    }

    return $this->providers;
  }

  /**
   * {@inheritdoc}
   */
  public function getActiveProvider(): ?array {
    $config = $this->configFactory->get('eb_ui.settings');
    $mode = $config->get('editor_mode') ?? 'auto';

    // Explicit YAML mode.
    if ($mode === 'yaml') {
      return NULL;
    }

    $providers = $this->getAvailableProviders();

    // No providers available.
    if (empty($providers)) {
      return NULL;
    }

    // Auto mode: return first available provider.
    if ($mode === 'auto') {
      return reset($providers);
    }

    // Specific provider selected.
    if (isset($providers[$mode])) {
      return $providers[$mode];
    }

    // Fallback to first provider if specified one doesn't exist.
    return reset($providers);
  }

  /**
   * {@inheritdoc}
   */
  public function isYamlMode(): bool {
    return $this->getActiveProvider() === NULL;
  }

}
