<?php

namespace Drupal\eb\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\eb\Service\DiscoveryServiceInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Controller for displaying discovered entity builder capabilities.
 */
class EbDiscoveryController extends ControllerBase {

  /**
   * Constructor.
   *
   * @param \Drupal\eb\Service\DiscoveryServiceInterface $discoveryService
   *   The discovery service.
   */
  public function __construct(
    protected DiscoveryServiceInterface $discoveryService,
  ) {}

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

  /**
   * Display discovery information.
   *
   * @return array
   *   Render array.
   */
  public function discoveryInfo(): array {
    $build = [];

    // Attach admin library for filtering.
    $build['#attached']['library'][] = 'eb/admin.discovery';

    $build['help'] = [
      '#markup' => '<p>' . $this->t('This page shows all capabilities discovered by Entity Builder. These are the field types, widgets, formatters, and entity types available for use in your architecture definitions.') . '</p>',
    ];

    // Filter input.
    $build['filters'] = [
      '#type' => 'container',
      '#attributes' => ['class' => ['table-filter', 'js-show']],
    ];
    $build['filters']['text'] = [
      '#type' => 'search',
      '#title' => $this->t('Filter'),
      '#title_display' => 'invisible',
      '#size' => 60,
      '#placeholder' => $this->t('Filter by name, module, or type'),
      '#attributes' => [
        'class' => ['eb-discovery-filter-text'],
        'data-table' => '.eb-discovery-table',
        'autocomplete' => 'off',
      ],
    ];

    // Compatibility matrix (collapsible).
    $build['compatibility'] = [
      '#type' => 'details',
      '#title' => $this->t('Widget & Formatter Compatibility'),
      '#open' => FALSE,
      '#attributes' => ['class' => ['eb-compatibility-matrix']],
    ];
    $build['compatibility']['table'] = $this->buildCompatibilityMatrix();

    // Field Types - grouped by module.
    $field_types = $this->discoveryService->getAllFieldTypes();
    $build['field_types'] = [
      '#type' => 'details',
      '#title' => $this->t('Field Types (@count)', ['@count' => count($field_types)]),
      '#open' => TRUE,
    ];
    $build['field_types']['table'] = $this->buildFieldTypesTable($field_types);

    // Widgets - grouped by module.
    $widgets = $this->discoveryService->getAllWidgets();
    $build['widgets'] = [
      '#type' => 'details',
      '#title' => $this->t('Widgets (@count)', ['@count' => count($widgets)]),
      '#open' => FALSE,
    ];
    $build['widgets']['table'] = $this->buildWidgetsTable($widgets);

    // Formatters - grouped by module.
    $formatters = $this->discoveryService->getAllFormatters();
    $build['formatters'] = [
      '#type' => 'details',
      '#title' => $this->t('Formatters (@count)', ['@count' => count($formatters)]),
      '#open' => FALSE,
    ];
    $build['formatters']['table'] = $this->buildFormattersTable($formatters);

    // Entity Types.
    $entity_types = $this->discoveryService->getFieldableEntityTypes();
    $build['entity_types'] = [
      '#type' => 'details',
      '#title' => $this->t('Entity Types (@count)', ['@count' => count($entity_types)]),
      '#open' => FALSE,
    ];
    $build['entity_types']['table'] = $this->buildEntityTypesTable($entity_types);

    return $build;
  }

  /**
   * Builds the compatibility matrix table.
   *
   * @return array
   *   Render array for compatibility matrix.
   */
  protected function buildCompatibilityMatrix(): array {
    $field_types = $this->discoveryService->getAllFieldTypes();
    $all_widgets = $this->discoveryService->getAllWidgets();
    $all_formatters = $this->discoveryService->getAllFormatters();

    $rows = [];
    foreach ($field_types as $field_type_id => $field_type_info) {
      // Find compatible widgets.
      $compatible_widgets = [];
      foreach ($all_widgets as $widget_id => $widget_info) {
        if (in_array($field_type_id, $widget_info['field_types'] ?? [])) {
          $compatible_widgets[] = $widget_id;
        }
      }

      // Find compatible formatters.
      $compatible_formatters = [];
      foreach ($all_formatters as $formatter_id => $formatter_info) {
        if (in_array($field_type_id, $formatter_info['field_types'] ?? [])) {
          $compatible_formatters[] = $formatter_id;
        }
      }

      $rows[] = [
        'data' => [
          'field_type' => [
            'data' => ['#plain_text' => $field_type_info['label'] . ' (' . $field_type_id . ')'],
            'data-drupal-selector' => 'eb-discovery-filter-text-source',
          ],
          'widgets' => [
            'data' => !empty($compatible_widgets) ? implode(', ', $compatible_widgets) : $this->t('None'),
          ],
          'formatters' => [
            'data' => !empty($compatible_formatters) ? implode(', ', $compatible_formatters) : $this->t('None'),
          ],
        ],
        'data-module' => $field_type_info['module'] ?? 'core',
      ];
    }

    return [
      '#type' => 'table',
      '#header' => [
        $this->t('Field Type'),
        $this->t('Compatible Widgets'),
        $this->t('Compatible Formatters'),
      ],
      '#rows' => $rows,
      '#attributes' => ['class' => ['eb-discovery-table', 'eb-compatibility-table']],
      '#empty' => $this->t('No field types discovered.'),
    ];
  }

  /**
   * Builds field types table grouped by module.
   *
   * @param array $field_types
   *   Array of field types.
   *
   * @return array
   *   Render array.
   */
  protected function buildFieldTypesTable(array $field_types): array {
    // Group by module.
    $grouped = [];
    foreach ($field_types as $id => $info) {
      $module = $info['module'] ?? 'core';
      $grouped[$module][$id] = $info;
    }
    ksort($grouped);

    $rows = [];
    foreach ($grouped as $module => $types) {
      // Module header row.
      $rows[] = [
        'data' => [
          [
            'data' => $module,
            'colspan' => 4,
            'class' => ['eb-discovery-module-header'],
          ],
        ],
        'class' => ['eb-discovery-module-row'],
      ];

      foreach ($types as $id => $info) {
        $rows[] = [
          'data' => [
            'id' => [
              'data' => ['#plain_text' => $id],
              'data-drupal-selector' => 'eb-discovery-filter-text-source',
            ],
            'label' => [
              'data' => ['#plain_text' => $info['label']],
              'data-drupal-selector' => 'eb-discovery-filter-text-source',
            ],
            'category' => $info['category'] ?? $this->t('General'),
            'module' => [
              'data' => ['#plain_text' => $module],
              'data-drupal-selector' => 'eb-discovery-filter-text-source',
            ],
          ],
          'data-module' => $module,
        ];
      }
    }

    return [
      '#type' => 'table',
      '#header' => [
        $this->t('ID'),
        $this->t('Label'),
        $this->t('Category'),
        $this->t('Module'),
      ],
      '#rows' => $rows,
      '#attributes' => ['class' => ['eb-discovery-table']],
      '#empty' => $this->t('No field types found.'),
    ];
  }

  /**
   * Builds widgets table grouped by module.
   *
   * @param array $widgets
   *   Array of widgets.
   *
   * @return array
   *   Render array.
   */
  protected function buildWidgetsTable(array $widgets): array {
    // Group by module.
    $grouped = [];
    foreach ($widgets as $id => $info) {
      $module = $info['module'] ?? 'core';
      $grouped[$module][$id] = $info;
    }
    ksort($grouped);

    $rows = [];
    foreach ($grouped as $module => $items) {
      // Module header row.
      $rows[] = [
        'data' => [
          [
            'data' => $module,
            'colspan' => 4,
            'class' => ['eb-discovery-module-header'],
          ],
        ],
        'class' => ['eb-discovery-module-row'],
      ];

      foreach ($items as $id => $info) {
        $field_types = $info['field_types'] ?? [];
        $rows[] = [
          'data' => [
            'id' => [
              'data' => ['#plain_text' => $id],
              'data-drupal-selector' => 'eb-discovery-filter-text-source',
            ],
            'label' => [
              'data' => ['#plain_text' => $info['label']],
              'data-drupal-selector' => 'eb-discovery-filter-text-source',
            ],
            'field_types' => implode(', ', array_slice($field_types, 0, 5)) . (count($field_types) > 5 ? '...' : ''),
            'module' => [
              'data' => ['#plain_text' => $module],
              'data-drupal-selector' => 'eb-discovery-filter-text-source',
            ],
          ],
          'data-module' => $module,
        ];
      }
    }

    return [
      '#type' => 'table',
      '#header' => [
        $this->t('ID'),
        $this->t('Label'),
        $this->t('Compatible Field Types'),
        $this->t('Module'),
      ],
      '#rows' => $rows,
      '#attributes' => ['class' => ['eb-discovery-table']],
      '#empty' => $this->t('No widgets found.'),
    ];
  }

  /**
   * Builds formatters table grouped by module.
   *
   * @param array $formatters
   *   Array of formatters.
   *
   * @return array
   *   Render array.
   */
  protected function buildFormattersTable(array $formatters): array {
    // Group by module.
    $grouped = [];
    foreach ($formatters as $id => $info) {
      $module = $info['module'] ?? 'core';
      $grouped[$module][$id] = $info;
    }
    ksort($grouped);

    $rows = [];
    foreach ($grouped as $module => $items) {
      // Module header row.
      $rows[] = [
        'data' => [
          [
            'data' => $module,
            'colspan' => 4,
            'class' => ['eb-discovery-module-header'],
          ],
        ],
        'class' => ['eb-discovery-module-row'],
      ];

      foreach ($items as $id => $info) {
        $field_types = $info['field_types'] ?? [];
        $rows[] = [
          'data' => [
            'id' => [
              'data' => ['#plain_text' => $id],
              'data-drupal-selector' => 'eb-discovery-filter-text-source',
            ],
            'label' => [
              'data' => ['#plain_text' => $info['label']],
              'data-drupal-selector' => 'eb-discovery-filter-text-source',
            ],
            'field_types' => implode(', ', array_slice($field_types, 0, 5)) . (count($field_types) > 5 ? '...' : ''),
            'module' => [
              'data' => ['#plain_text' => $module],
              'data-drupal-selector' => 'eb-discovery-filter-text-source',
            ],
          ],
          'data-module' => $module,
        ];
      }
    }

    return [
      '#type' => 'table',
      '#header' => [
        $this->t('ID'),
        $this->t('Label'),
        $this->t('Compatible Field Types'),
        $this->t('Module'),
      ],
      '#rows' => $rows,
      '#attributes' => ['class' => ['eb-discovery-table']],
      '#empty' => $this->t('No formatters found.'),
    ];
  }

  /**
   * Builds entity types table.
   *
   * @param array $entity_types
   *   Array of entity types.
   *
   * @return array
   *   Render array.
   */
  protected function buildEntityTypesTable(array $entity_types): array {
    $rows = [];
    foreach ($entity_types as $id => $info) {
      $bundles = $this->discoveryService->getBundlesForEntityType($id);
      $rows[] = [
        'data' => [
          'id' => [
            'data' => ['#plain_text' => $id],
            'data-drupal-selector' => 'eb-discovery-filter-text-source',
          ],
          'label' => [
            'data' => ['#plain_text' => $info['label']],
            'data-drupal-selector' => 'eb-discovery-filter-text-source',
          ],
          'bundles' => count($bundles),
          'group' => $info['group'] ?? $this->t('Content'),
        ],
      ];
    }

    return [
      '#type' => 'table',
      '#header' => [
        $this->t('ID'),
        $this->t('Label'),
        $this->t('Bundles'),
        $this->t('Group'),
      ],
      '#rows' => $rows,
      '#attributes' => ['class' => ['eb-discovery-table']],
      '#empty' => $this->t('No entity types found.'),
    ];
  }

}
