<?php

namespace Drupal\eb\Plugin\EbValidator;

use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\eb\Attribute\EbValidator;
use Drupal\eb\PluginBase\ValidatorBase;
use Drupal\eb\Result\ValidationResult;
use Drupal\eb\Service\DiscoveryServiceInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Validates formatter compatibility with field types.
 */
#[EbValidator(
  id: 'formatter_compatibility',
  label: new TranslatableMarkup('Formatter Compatibility Validator'),
  description: new TranslatableMarkup('Validates that formatters are compatible with field types'),
)]
class FormatterCompatibilityValidator extends ValidatorBase implements ContainerFactoryPluginInterface {

  /**
   * Constructor.
   *
   * @param array<string, mixed> $configuration
   *   Plugin configuration.
   * @param string $plugin_id
   *   Plugin ID.
   * @param mixed $plugin_definition
   *   Plugin definition.
   * @param \Drupal\eb\Service\DiscoveryServiceInterface $discoveryService
   *   Discovery service.
   */
  public function __construct(
    array $configuration,
    string $plugin_id,
    mixed $plugin_definition,
    protected DiscoveryServiceInterface $discoveryService,
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    // @phpstan-ignore-next-line
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('eb.discovery_service'),
    );
  }

  /**
   * {@inheritdoc}
   */
  public function validate(array $data): ValidationResult {
    $result = new ValidationResult();

    // Only validate if field_type and formatter are both present.
    if (empty($data['field_type']) || empty($data['formatter'])) {
      return $result;
    }

    $field_type = $data['field_type'];

    // Extract formatter type from array or use as string.
    $formatterData = $data['formatter'];
    $formatter = is_array($formatterData) ? ($formatterData['type'] ?? NULL) : $formatterData;

    // Skip validation if no formatter type specified.
    if ($formatter === NULL) {
      return $result;
    }

    // Check if formatter exists.
    if (!$this->discoveryService->formatterExists($formatter)) {
      $result->addError(
        $this->t('Formatter "@formatter" does not exist.', [
          '@formatter' => $formatter,
        ]),
        'formatter',
        'formatter_not_found'
      );
      return $result;
    }

    // Get compatible formatters for this field type.
    $compatible_formatters = $this->discoveryService->getFormattersForFieldType($field_type);

    // Check if formatter is compatible.
    if (!isset($compatible_formatters[$formatter])) {
      $result->addError(
        $this->t('Formatter "@formatter" is not compatible with field type "@field_type". Compatible formatters: @formatters', [
          '@formatter' => $formatter,
          '@field_type' => $field_type,
          '@formatters' => implode(', ', array_keys($compatible_formatters)),
        ]),
        'formatter',
        'incompatible_formatter'
      );
    }

    return $result;
  }

}
