<?php

namespace Drupal\eb\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Url;
use Drupal\eb\Entity\EbDefinition;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Controller for displaying entity builder definition details.
 */
class EbDefinitionController extends ControllerBase {

  /**
   * Mapping of field types to Drupal core field icon CSS classes.
   *
   * These icons are from field_ui/css/field_ui.icons.theme.css.
   */
  protected const FIELD_TYPE_ICONS = [
    // Text types.
    'string' => 'field-icon-plain_text',
    'string_long' => 'field-icon-plain_text',
    'text' => 'field-icon-formatted_text',
    'text_long' => 'field-icon-formatted_text',
    'text_with_summary' => 'field-icon-formatted_text',
    // Number types.
    'integer' => 'field-icon-number',
    'decimal' => 'field-icon-number',
    'float' => 'field-icon-number',
    'list_integer' => 'field-icon-number',
    'list_float' => 'field-icon-number',
    // Selection types.
    'list_string' => 'field-icon-selection_list',
    'boolean' => 'field-icon-boolean',
    // Reference types.
    'entity_reference' => 'field-icon-reference',
    'entity_reference_revisions' => 'field-icon-reference',
    // Date/time types.
    'datetime' => 'field-icon-date_time',
    'timestamp' => 'field-icon-date_time',
    'daterange' => 'field-icon-date_time',
    'created' => 'field-icon-date_time',
    'changed' => 'field-icon-date_time',
    // Media types.
    'file' => 'field-icon-file_upload',
    'image' => 'field-icon-file_upload',
    // Communication types.
    'email' => 'field-icon-email',
    'telephone' => 'field-icon-telephone',
    'link' => 'field-icon-link',
    // Other.
    'comment' => 'field-icon-comment',
  ];

  /**
   * The date formatter service.
   *
   * @var \Drupal\Core\Datetime\DateFormatterInterface
   */
  protected DateFormatterInterface $dateFormatter;

  /**
   * Constructs a new EbDefinitionController.
   *
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
   *   The date formatter service.
   */
  public function __construct(DateFormatterInterface $date_formatter) {
    $this->dateFormatter = $date_formatter;
  }

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

  /**
   * Returns the page title for a definition.
   *
   * @param \Drupal\eb\Entity\EbDefinition $eb_definition
   *   The definition entity.
   *
   * @return string
   *   The page title.
   */
  public function title(EbDefinition $eb_definition): string {
    return $eb_definition->label() ?? '';
  }

  /**
   * Displays a definition's details.
   *
   * @param \Drupal\eb\Entity\EbDefinition $eb_definition
   *   The definition entity.
   *
   * @return array
   *   Render array.
   */
  public function view(EbDefinition $eb_definition): array {
    $build = [];

    // Attach admin library.
    $build['#attached']['library'][] = 'eb/admin.listing';
    // Attach field type icon libraries from core modules (only if installed).
    $icon_libraries = [
      'field_ui' => 'field_ui/drupal.field_ui.manage_fields',
      'text' => 'text/drupal.text-icon',
      'options' => 'options/drupal.options-icon',
      'file' => 'file/drupal.file-icon',
      'link' => 'link/drupal.link-icon',
      'telephone' => 'telephone/drupal.telephone-icon',
      'media' => 'media/drupal.media-icon',
      'comment' => 'comment/drupal.comment-icon',
    ];
    foreach ($icon_libraries as $module => $library) {
      if ($this->moduleHandler()->moduleExists($module)) {
        $build['#attached']['library'][] = $library;
      }
    }

    // Header section with status and actions.
    $build['header'] = [
      '#type' => 'container',
      '#attributes' => ['class' => ['eb-definition-header']],
    ];

    // Status badge.
    $status = $eb_definition->getApplicationStatus();
    $status_labels = [
      'draft' => $this->t('Draft'),
      'applied' => $this->t('Applied'),
      'outdated' => $this->t('Outdated'),
    ];
    $status_classes = [
      'draft' => 'admin-missing',
      'applied' => 'admin-enabled',
      'outdated' => 'admin-required',
    ];

    $build['header']['status'] = [
      '#markup' => '<div class="eb-definition-status"><span class="eb-status-badge ' . ($status_classes[$status] ?? '') . '">' . ($status_labels[$status] ?? $status) . '</span></div>',
    ];

    // Action buttons.
    $build['header']['actions'] = [
      '#type' => 'container',
      '#attributes' => ['class' => ['eb-definition-actions']],
    ];

    $build['header']['actions']['apply'] = [
      '#type' => 'link',
      '#title' => $this->t('Apply Definition'),
      '#url' => $eb_definition->toUrl('apply-form'),
      '#attributes' => [
        'class' => ['button', 'button--primary'],
      ],
    ];

    // Edit button - only shown if eb_ui module is installed.
    if ($this->moduleHandler()->moduleExists('eb_ui')) {
      $build['header']['actions']['edit'] = [
        '#type' => 'link',
        '#title' => $this->t('Edit'),
        '#url' => Url::fromRoute('eb_ui.edit', ['definition_id' => $eb_definition->id()]),
        '#attributes' => [
          'class' => ['button'],
        ],
      ];
    }

    $build['header']['actions']['delete'] = [
      '#type' => 'link',
      '#title' => $this->t('Delete'),
      '#url' => $eb_definition->toUrl('delete-form'),
      '#attributes' => [
        'class' => ['button', 'button--danger'],
      ],
    ];

    // Description.
    if ($description = $eb_definition->getDescription()) {
      $build['description'] = [
        '#type' => 'container',
        '#attributes' => ['class' => ['eb-definition-description']],
        'content' => [
          '#markup' => '<p>' . $description . '</p>',
        ],
      ];
    }

    // Summary statistics cards.
    $bundle_count = count($eb_definition->getBundleDefinitions());
    $field_count = count($eb_definition->getFieldDefinitions());
    $display_count = count($eb_definition->getDisplayFieldDefinitions());
    $menu_count = count($eb_definition->getMenuDefinitions());

    $build['summary_cards'] = [
      '#type' => 'container',
      '#attributes' => ['class' => ['eb-summary-cards']],
    ];

    $build['summary_cards']['bundles'] = [
      '#type' => 'inline_template',
      '#template' => '<div class="eb-summary-card"><span class="eb-summary-card__count">{{ count }}</span><span class="eb-summary-card__label">{{ label }}</span></div>',
      '#context' => [
        'count' => $bundle_count,
        'label' => $this->t('Bundles'),
      ],
    ];

    $build['summary_cards']['fields'] = [
      '#type' => 'inline_template',
      '#template' => '<div class="eb-summary-card"><span class="eb-summary-card__count">{{ count }}</span><span class="eb-summary-card__label">{{ label }}</span></div>',
      '#context' => [
        'count' => $field_count,
        'label' => $this->t('Fields'),
      ],
    ];

    $build['summary_cards']['displays'] = [
      '#type' => 'inline_template',
      '#template' => '<div class="eb-summary-card"><span class="eb-summary-card__count">{{ count }}</span><span class="eb-summary-card__label">{{ label }}</span></div>',
      '#context' => [
        'count' => $display_count,
        'label' => $this->t('Displays'),
      ],
    ];

    if ($menu_count > 0) {
      $build['summary_cards']['menus'] = [
        '#type' => 'inline_template',
        '#template' => '<div class="eb-summary-card"><span class="eb-summary-card__count">{{ count }}</span><span class="eb-summary-card__label">{{ label }}</span></div>',
        '#context' => [
          'count' => $menu_count,
          'label' => $this->t('Menus'),
        ],
      ];
    }

    // Metadata section.
    $build['metadata'] = [
      '#type' => 'details',
      '#title' => $this->t('Definition Metadata'),
      '#open' => TRUE,
    ];

    $build['metadata']['table'] = [
      '#type' => 'table',
      '#rows' => [
        [
          ['data' => $this->t('Machine name'), 'header' => TRUE],
          $eb_definition->id(),
        ],
        [
          ['data' => $this->t('Entity Types'), 'header' => TRUE],
          $this->formatEntityTypes($eb_definition),
        ],
        [
          ['data' => $this->t('Application Status'), 'header' => TRUE],
          $status_labels[$status] ?? $status,
        ],
        [
          ['data' => $this->t('Applied Date'), 'header' => TRUE],
          $eb_definition->getAppliedDate() ?
          $this->dateFormatter->format($eb_definition->getAppliedDate(), 'medium') :
          ['data' => $this->t('Never'), 'class' => ['eb-warning-text']],
        ],
        [
          ['data' => $this->t('Created'), 'header' => TRUE],
          $eb_definition->getCreatedTime() ?
          $this->dateFormatter->format($eb_definition->getCreatedTime(), 'medium') :
          $this->t('Unknown'),
        ],
        [
          ['data' => $this->t('Changed'), 'header' => TRUE],
          $eb_definition->getChangedTime() ?
          $this->dateFormatter->format($eb_definition->getChangedTime(), 'medium') :
          $this->t('Unknown'),
        ],
      ],
    ];

    // Bundles section.
    $bundle_definitions = $eb_definition->getBundleDefinitions();
    $build['bundles'] = [
      '#type' => 'details',
      '#title' => $this->t('Bundles (@count)', ['@count' => count($bundle_definitions)]),
      '#open' => TRUE,
    ];

    if (!empty($bundle_definitions)) {
      $bundle_rows = [];
      foreach ($bundle_definitions as $bundle) {
        $bundle_id = $bundle['machine_name'] ?? $bundle['bundle_id'] ?? 'unknown';
        $bundle_label = $bundle['label'] ?? $bundle_id;
        $fields_for_bundle = $eb_definition->getFieldsForBundle($bundle_id);

        $bundle_rows[] = [
          $bundle_id,
          $bundle_label,
          count($fields_for_bundle),
          $bundle['description'] ?? '',
        ];
      }

      $build['bundles']['table'] = [
        '#type' => 'table',
        '#header' => [
          $this->t('Machine Name'),
          $this->t('Label'),
          $this->t('Fields'),
          $this->t('Description'),
        ],
        '#rows' => $bundle_rows,
      ];
    }
    else {
      $build['bundles']['empty'] = [
        '#markup' => '<p>' . $this->t('No bundles defined.') . '</p>',
      ];
    }

    // Fields section.
    $field_definitions = $eb_definition->getFieldDefinitions();
    $build['fields'] = [
      '#type' => 'details',
      '#title' => $this->t('Fields (@count)', ['@count' => count($field_definitions)]),
      '#open' => FALSE,
    ];

    if (!empty($field_definitions)) {
      $field_rows = [];
      foreach ($field_definitions as $field) {
        $field_type = $field['field_type'] ?? $field['type'] ?? 'unknown';
        $field_rows[] = [
          $field['field_name'] ?? $field['machine_name'] ?? 'unknown',
          $field['label'] ?? '',
          ['data' => $this->formatFieldTypeWithIcon($field_type)],
          $field['bundle'] ?? '',
          !empty($field['required']) ? $this->t('Yes') : $this->t('No'),
        ];
      }

      $build['fields']['table'] = [
        '#type' => 'table',
        '#header' => [
          $this->t('Machine Name'),
          $this->t('Label'),
          $this->t('Type'),
          $this->t('Bundle'),
          $this->t('Required'),
        ],
        '#rows' => $field_rows,
      ];
    }
    else {
      $build['fields']['empty'] = [
        '#markup' => '<p>' . $this->t('No fields defined.') . '</p>',
      ];
    }

    // Field groups section.
    $field_group_definitions = $eb_definition->getFieldGroupDefinitions();
    if (!empty($field_group_definitions)) {
      $build['field_groups'] = [
        '#type' => 'details',
        '#title' => $this->t('Field Groups (@count)', ['@count' => count($field_group_definitions)]),
        '#open' => FALSE,
      ];

      $group_rows = [];
      foreach ($field_group_definitions as $group) {
        $group_rows[] = [
          $group['group_name'] ?? '',
          $group['label'] ?? '',
          $group['format_type'] ?? '',
          $group['display_type'] ?? '',
          $group['mode'] ?? 'default',
          $group['bundle'] ?? '',
        ];
      }

      $build['field_groups']['table'] = [
        '#type' => 'table',
        '#header' => [
          $this->t('Group Name'),
          $this->t('Label'),
          $this->t('Format'),
          $this->t('Display Type'),
          $this->t('Mode'),
          $this->t('Bundle'),
        ],
        '#rows' => $group_rows,
      ];
    }

    // Display field configurations section (flat format).
    $display_field_definitions = $eb_definition->getDisplayFieldDefinitions();
    $build['displays'] = [
      '#type' => 'details',
      '#title' => $this->t('Display Field Configurations (@count)', ['@count' => count($display_field_definitions)]),
      '#open' => FALSE,
    ];

    if (!empty($display_field_definitions)) {
      $display_rows = [];
      foreach ($display_field_definitions as $displayField) {
        $display_rows[] = [
          $displayField['field_name'] ?? '',
          $displayField['display_type'] ?? 'form',
          $displayField['mode'] ?? 'default',
          $displayField['bundle'] ?? '',
          $displayField['widget'] ?? $displayField['formatter'] ?? '',
          $displayField['group'] ?? '',
        ];
      }

      $build['displays']['table'] = [
        '#type' => 'table',
        '#header' => [
          $this->t('Field'),
          $this->t('Type'),
          $this->t('Mode'),
          $this->t('Bundle'),
          $this->t('Widget/Formatter'),
          $this->t('Group'),
        ],
        '#rows' => $display_rows,
      ];
    }
    else {
      $build['displays']['empty'] = [
        '#markup' => '<p>' . $this->t('No display field configurations defined.') . '</p>',
      ];
    }

    // Menu definitions section (if any).
    $menu_definitions = $eb_definition->getMenuDefinitions();
    if (!empty($menu_definitions)) {
      $build['menus'] = [
        '#type' => 'details',
        '#title' => $this->t('Menus (@count)', ['@count' => count($menu_definitions)]),
        '#open' => FALSE,
      ];

      $menu_rows = [];
      foreach ($menu_definitions as $menu) {
        $menu_rows[] = [
          $menu['menu_id'] ?? $menu['machine_name'] ?? 'unknown',
          $menu['label'] ?? '',
          $menu['description'] ?? '',
        ];
      }

      $build['menus']['table'] = [
        '#type' => 'table',
        '#header' => [
          $this->t('Machine Name'),
          $this->t('Label'),
          $this->t('Description'),
        ],
        '#rows' => $menu_rows,
      ];
    }

    // Back link.
    $build['back'] = [
      '#type' => 'link',
      '#title' => $this->t('Back to list'),
      '#url' => Url::fromRoute('entity.eb_definition.collection'),
      '#attributes' => ['class' => ['eb-back-link']],
    ];

    return $build;
  }

  /**
   * Formats entity types for display.
   *
   * @param \Drupal\eb\Entity\EbDefinition $entity
   *   The definition entity.
   *
   * @return string|\Drupal\Core\StringTranslation\TranslatableMarkup
   *   Comma-separated list of entity types or 'Not set'.
   */
  protected function formatEntityTypes(EbDefinition $entity): string|TranslatableMarkup {
    $entity_types = $entity->getEntityTypes();
    if (empty($entity_types)) {
      return $this->t('Not set');
    }
    return implode(', ', $entity_types);
  }

  /**
   * Gets the icon CSS class for a field type.
   *
   * @param string $field_type
   *   The field type machine name.
   *
   * @return string
   *   The CSS class for the icon, or fallback class for unknown types.
   */
  protected function getFieldTypeIconClass(string $field_type): string {
    return self::FIELD_TYPE_ICONS[$field_type] ?? 'field-option__icon';
  }

  /**
   * Formats a field type with an icon for display.
   *
   * @param string $field_type
   *   The field type machine name.
   *
   * @return array
   *   A render array with the icon and label.
   */
  protected function formatFieldTypeWithIcon(string $field_type): array {
    $icon_class = $this->getFieldTypeIconClass($field_type);
    return [
      '#type' => 'inline_template',
      '#template' => '<span class="eb-field-type"><span class="eb-field-type__icon {{ icon_class }}"></span><span class="eb-field-type__label">{{ field_type }}</span></span>',
      '#context' => [
        'icon_class' => $icon_class,
        'field_type' => $field_type,
      ],
    ];
  }

}
