<?php

namespace Drupal\nodehive_core;

use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityListBuilder;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * Provides a list controller for the space entity type.
 */
class SpaceListBuilder extends EntityListBuilder {

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

  /**
   * The request stack.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected $requestStack;

  /**
   * The node entity storage.
   *
   * @var \Drupal\Core\Entity\EntityStorageInterface
   */
  protected $nodeStorage;

  /**
   * Constructs a new NodehiveSpaceListBuilder object.
   *
   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
   *   The entity type definition.
   * @param \Drupal\Core\Entity\EntityStorageInterface $storage
   *   The entity storage class.
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
   *   The date formatter service.
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The request stack.
   * @param \Drupal\Core\Entity\EntityStorageInterface $node_storage
   *   The node entity storage.
   */
  public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, DateFormatterInterface $date_formatter, RequestStack $request_stack, EntityStorageInterface $node_storage) {
    parent::__construct($entity_type, $storage);
    $this->dateFormatter = $date_formatter;
    $this->requestStack = $request_stack;
    $this->nodeStorage = $node_storage;
  }

  /**
   * {@inheritdoc}
   */
  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
    return new static(
      $entity_type,
      $container->get('entity_type.manager')->getStorage($entity_type->id()),
      $container->get('date.formatter'),
      $container->get('request_stack'),
      $container->get('entity_type.manager')->getStorage('node')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function render() {
    $build = [];

    $total = $this->getStorage()
      ->getQuery()
      ->accessCheck(TRUE)
      ->count()
      ->execute();

    $request = $this->requestStack->getCurrentRequest();
    $search = $request->query->get('search', '');
    $type = $request->query->get('type', '');

    // Build filter bar as raw markup to avoid Drupal form wrapper styling.
    $has_filters = ($search !== '' || $type !== '');
    $reset_link = '';
    if ($has_filters) {
      $reset_url = Url::fromRoute('entity.nodehive_space.collection')->toString();
      $reset_link = '<a href="' . $reset_url . '" class="button button--small">' . $this->t('Reset') . '</a>';
    }

    // Type options.
    $type_options = [
      'full_website' => 'Website',
      'directory' => 'Website Subdirectory',
      'database' => 'Database (no frontend)',
      'other' => 'Other',
    ];
    $type_options_html = '<option value="">- Type -</option>';
    foreach ($type_options as $key => $label) {
      $selected = ($type === $key) ? ' selected' : '';
      $type_options_html .= '<option value="' . $key . '"' . $selected . '>' . $label . '</option>';
    }

    $build['filters'] = [
      '#type' => 'inline_template',
      '#template' => '<form method="get" class="space-list-filters">'
      . '<input type="search" name="search" placeholder="{{ search_placeholder }}" value="{{ search_value }}" />'
      . '<select name="type">{{ type_options | raw }}</select>'
      . '<button type="submit" class="button button--primary button--small">{{ lbl_filter }}</button>'
      . '{{ reset | raw }}'
      . '<span class="space-list-count">{{ total_label }}</span>'
      . '</form>',
      '#context' => [
        'search_placeholder' => $this->t('Search by name...'),
        'search_value' => $search,
        'type_options' => $type_options_html,
        'lbl_filter' => $this->t('Filter'),
        'reset' => $reset_link,
        'total_label' => $this->t('@total spaces', ['@total' => $total]),
      ],
      '#weight' => -10,
    ];

    // Load entities.
    $entity_ids = $this->getEntityIds();
    $entities = $this->storage->loadMultiple($entity_ids);

    if (empty($entities)) {
      $build['empty'] = [
        '#markup' => $this->t(
          "No spaces available, please <a href='@link'>create a new space.</a>",
          ['@link' => Url::fromUserInput('/space/add')->toString()]
        ),
        '#weight' => 1,
      ];
    }
    else {
      $enabled_entities = [];
      $disabled_entities = [];
      foreach ($entities as $entity) {
        if ((bool) $entity->get('status')->value) {
          $enabled_entities[] = $entity;
        }
        else {
          $disabled_entities[] = $entity;
        }
      }

      $build['sections'] = [
        '#type' => 'container',
        '#attributes' => [
          'class' => ['space-list-sections'],
        ],
        '#weight' => 1,
      ];

      if (!empty($enabled_entities)) {
        $build['sections']['enabled'] = $this->buildCardSection($this->t('Enabled Spaces'), $enabled_entities, 'enabled');
      }

      if (!empty($disabled_entities)) {
        $build['sections']['disabled'] = $this->buildCardSection($this->t('Disabled Spaces'), $disabled_entities, 'disabled');
      }
    }

    // Pager.
    $build['pager'] = [
      '#type' => 'pager',
      '#weight' => 10,
    ];

    $build['#attached']['library'][] = 'nodehive_core/nodehive-spaces-cards';

    return $build;
  }

  /**
   * Builds a grouped card section.
   *
   * @param \Drupal\Core\StringTranslation\TranslatableMarkup|string $label
   *   The section label.
   * @param \Drupal\Core\Entity\EntityInterface[] $entities
   *   The entities to render.
   * @param string $modifier
   *   A CSS modifier for the section.
   *
   * @return array
   *   A render array.
   */
  protected function buildCardSection($label, array $entities, string $modifier) {
    $section = [
      '#type' => 'container',
      '#attributes' => [
        'class' => ['space-list-section', 'space-list-section--' . $modifier],
      ],
    ];

    $section['heading'] = [
      '#type' => 'html_tag',
      '#tag' => 'h2',
      '#attributes' => [
        'class' => ['space-list-section__heading'],
      ],
      '#value' => $label,
    ];

    $section['cards'] = [
      '#type' => 'container',
      '#attributes' => [
        'class' => ['space-list-cards'],
      ],
    ];

    foreach ($entities as $entity) {
      $section['cards'][] = $this->buildCard($entity);
    }

    return $section;
  }

  /**
   * Builds a card render array for a single space entity.
   */
  protected function buildCard(EntityInterface $entity) {
    // Preview screenshot URL.
    $external_url = '';
    if (!$entity->get('space_url')->isEmpty()) {
      $first_link = $entity->get('space_url')->first()->getValue();
      $external_url = $first_link['uri'] ?? '';
    }

    $screenshot_url = '';
    if ($external_url) {
      $screenshot_url = 'https://preview.nodehive.com/api/screenshot?resX=1600&resY=900&outFormat=jpg&waitTime=200&isFullPage=false&dismissModals=false&url=' . $external_url;
    }

    // Status.
    $is_enabled = (bool) $entity->get('status')->value;

    // Space type.
    $type_label = '';
    if ($entity->space_type->value) {
      $type_values = nodehive_core_space_type_allowed_values(
        $entity->space_type->getFieldDefinition(),
        $entity,
        TRUE
      );
      $type_label = $type_values[$entity->space_type->value] ?? '';
    }

    // Hosting provider.
    $hosting = '';
    if ($entity->hasField('hosting_provider') && !$entity->hosting_provider->isEmpty()) {
      $hosting_values = [
        'vercel' => 'Vercel',
        'netlify' => 'Netlify',
        'netnode_cloud' => 'NETNODE.cloud',
        'other' => 'Other',
      ];
      $hosting = $hosting_values[$entity->hosting_provider->value] ?? $entity->hosting_provider->value;
    }

    // Counts.
    $editors_count = $entity->editors->count();
    $contents_count = (int) $this->nodeStorage->getQuery()
      ->accessCheck(FALSE)
      ->condition('nodehive_space', $entity->id())
      ->count()
      ->execute();

    // URLs.
    $editor_url = '/space/' . $entity->id() . '/content';

    // Build the card as a single clickable link.
    $card = [
      '#type' => 'html_tag',
      '#tag' => 'a',
      '#attributes' => [
        'class' => ['space-list-card', $is_enabled ? 'space-list-card--enabled' : 'space-list-card--disabled'],
        'href' => $editor_url,
      ],
    ];

    // Thumbnail.
    $thumbnail_style = $screenshot_url ? 'background-image: url("' . $screenshot_url . '")' : '';
    $card['thumbnail'] = [
      '#type' => 'html_tag',
      '#tag' => 'div',
      '#attributes' => [
        'class' => ['space-list-card__thumbnail'],
        'style' => $thumbnail_style,
      ],
    ];

    // Status badge on thumbnail.
    if (!$is_enabled) {
      $card['thumbnail']['badge'] = [
        '#type' => 'html_tag',
        '#tag' => 'span',
        '#attributes' => ['class' => ['space-list-card__badge', 'space-list-card__badge--disabled']],
        '#value' => $this->t('Disabled'),
      ];
    }

    // Body.
    $card['body'] = [
      '#type' => 'html_tag',
      '#tag' => 'div',
      '#attributes' => ['class' => ['space-list-card__body']],
    ];

    // Title.
    $card['body']['title'] = [
      '#type' => 'html_tag',
      '#tag' => 'div',
      '#attributes' => [
        'class' => ['space-list-card__title'],
      ],
      '#value' => $entity->label(),
    ];

    // Domain URL.
    if ($external_url) {
      $domain = parse_url($external_url, PHP_URL_HOST) ?: $external_url;
      $card['body']['domain'] = [
        '#type' => 'html_tag',
        '#tag' => 'div',
        '#attributes' => [
          'class' => ['space-list-card__domain'],
        ],
        '#value' => $domain,
      ];
    }

    // Meta line.
    $meta_parts = [];
    if ($type_label) {
      $meta_parts[] = $type_label;
    }
    if ($hosting) {
      $meta_parts[] = $hosting;
    }
    if (!empty($meta_parts)) {
      $card['body']['meta'] = [
        '#type' => 'html_tag',
        '#tag' => 'div',
        '#attributes' => ['class' => ['space-list-card__meta']],
        '#value' => implode(' · ', $meta_parts),
      ];
    }

    // Stats.
    $card['body']['stats'] = [
      '#type' => 'html_tag',
      '#tag' => 'div',
      '#attributes' => ['class' => ['space-list-card__stats']],
      '#value' => $this->t('@contents contents · @editors editors', [
        '@contents' => $contents_count,
        '@editors' => $editors_count,
      ]),
    ];

    return $card;
  }

  /**
   * {@inheritdoc}
   */
  protected function getEntityIds() {
    $request = $this->requestStack->getCurrentRequest();
    $search = $request->query->get('search', '');
    $type = $request->query->get('type', '');

    $query = $this->getStorage()->getQuery()
      ->accessCheck(TRUE)
      ->sort('status', 'DESC')
      ->sort($this->entityType->getKey('id'), 'DESC');

    if ($search !== '') {
      $query->condition('label', $search, 'CONTAINS');
    }

    if ($type !== '') {
      $query->condition('space_type', $type);
    }

    if ($this->limit) {
      $query->pager($this->limit);
    }

    return $query->execute();
  }

}
