<?php

namespace Drupal\nodehive_core\Controller;

use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Link;
use Drupal\Core\Render\Markup;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\Url;
use Drupal\node\NodeInterface;
use Drupal\nodehive_core\Helper\NodehiveLanguageHelper;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Response;

/**
 * Controller for rendering node preview in the 'rag' view mode.
 */
class NodehiveActivityBlockController extends ControllerBase {

  /**
   * The entity type manager service.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

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

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $currentUser;

  /**
   * The renderer.
   *
   * @var \Drupal\Core\Render\RendererInterface
   */
  protected $renderer;

  /**
   * The language helper service.
   *
   * @var \Drupal\nodehive_core\Helper\NodehiveLanguageHelper
   */
  protected $languageHelper;

  /**
   * The time service.
   *
   * @var \Drupal\Component\Datetime\TimeInterface
   */
  protected $time;

  /**
   * Constructs a NodehiveActivityBlockController.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager service.
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
   *   The date formatter service.
   * @param \Drupal\Core\Session\AccountProxyInterface $current_user
   *   The current user service.
   * @param \Drupal\Core\Render\RendererInterface $renderer
   *   The renderer.
   * @param \Drupal\nodehive_core\Helper\NodehiveLanguageHelper $language_helper
   *   The language helper service.
   * @param \Drupal\Component\Datetime\TimeInterface $time
   *   The time service.
   */
  public function __construct(
    EntityTypeManagerInterface $entity_type_manager,
    DateFormatterInterface $date_formatter,
    AccountProxyInterface $current_user,
    RendererInterface $renderer,
    NodehiveLanguageHelper $language_helper,
    TimeInterface $time,
  ) {
    $this->entityTypeManager = $entity_type_manager;
    $this->dateFormatter = $date_formatter;
    $this->currentUser = $current_user;
    $this->renderer = $renderer;
    $this->languageHelper = $language_helper;
    $this->time = $time;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity_type.manager'),
      $container->get('date.formatter'),
      $container->get('current_user'),
      $container->get('renderer'),
      $container->get('nodehive_core.language_helper'),
      $container->get('datetime.time')
    );
  }

  /**
   * Renders a preview of nodes based on the action.
   *
   * @param string $action
   *   The action to determine which nodes to render.
   * @param string $number_of_items
   *   The number of items.
   * @param string $workflow
   *   The workflow.
   *
   * @return \Symfony\Component\HttpFoundation\Response
   *   The response containing the rendered content.
   */
  public function renderAction($action, $number_of_items, $workflow) {
    $nodes = ($action === 'assigned-to-me') ? $this->getAssignedToMeContent($number_of_items) : $this->getTeamContent($number_of_items);

    if (empty($nodes)) {
      $build = [
        '#type' => 'markup',
        '#markup' => '<div class="no-activity">' . $this->t('No activity') . '</div>',
      ];
      return new Response($this->renderer->renderRoot($build));
    }

    $header = [
      'actions' => '',
      'title' => $this->t('Title'),
      'content_type' => $this->t('Content Type'),
      'space' => "Space",
      'language' => $this->t('Languages'),
      'author' => $this->t('Author'),
      'status' => $this->t('Status'),
      'last_edited' => $this->t('Last update'),
    ];

    $rows = $this->buildNodeRows($nodes, $workflow);
    $build = [
      '#type' => 'table',
      '#header' => $header,
    ];

    foreach ($rows as $row) {
      $build[] = $row;
    }

    $build['#attached']['library'][] = 'nodehive_core/activity-block';

    return new Response($this->renderer->renderRoot($build));
  }

  /**
   * Builds the rows for the nodes table.
   *
   * @param array $nodes
   *   The nodes to render.
   * @param string $workflow
   *   The workflow.
   *
   * @return array
   *   An array of table rows.
   */
  protected function buildNodeRows(array $nodes, $workflow) {
    $rows = [];
    foreach ($nodes as $node) {
      assert($node instanceof NodeInterface);
      $node_type = $this->entityTypeManager->getStorage('node_type')->load($node->bundle());
      $rows[] = [
        'actions' => ['#markup' => Markup::create($this->buildActionIcons($node))],
        'title' => [
          '#type' => 'link',
          '#title' => $node->label(),
          '#url' => Url::fromRoute('entity.node.canonical', ['node' => $node->id()]),
          '#attributes' => [
            'class' => [
              'truncate',
              'text-ellipsis',
              'block',
              'max-w-72',
            ],
          ],
        ],
        'content_type' => [
          '#type' => 'markup',
          '#markup' => '<span class="truncate text-ellipsis block max-w-36">' . ($node_type ? $node_type->label() : $node->bundle()) . '</span>',
        ],
        'space' => ['#markup' => $this->getSpaceLink($node)],
        'language' => $this->buildLanguageSwitcher($node),
        'author' => ['#markup' => $this->getAuthorName($node)],
        'status' => ['#markup' => $this->buildNodeStatus($node)],
        'last_edited' => [
          '#type' => 'markup',
          '#markup' => '<span class="truncate text-ellipsis block max-w-36 text-sm text-gray-600">' . $this->dateFormatter->formatInterval($this->time->getRequestTime() - $node->getChangedTime(), 1) . '</span>',
        ],
      ];
    }
    return $rows;
  }

  /**
   * Builds action icon buttons for a node (eye, edit, external link).
   */
  protected function buildActionIcons(NodeInterface $node) {
    $icons = '';
    $icon_class = 'activity-action';

    // Get space and frontend URL for visual editor and external link.
    $space = NULL;
    $frontend_url = '';
    if ($node->hasField('nodehive_space') && !$node->get('nodehive_space')->isEmpty()) {
      $space = $this->entityTypeManager->getStorage('nodehive_space')->load($node->get('nodehive_space')->target_id);
    }

    if ($space && $space->hasField('space_url') && !$space->get('space_url')->isEmpty()) {
      $space_urls = $space->get('space_url')->getValue();
      $base_url = $space_urls[0]['uri'] ?? '';
      if ($base_url) {
        $internal_path = $node->toUrl()->toString();
        $frontend_url = rtrim($base_url, '/') . $internal_path;

        // Eye icon — visual editor.
        $ve_url = Url::fromRoute('nodehive_visualeditor.visual_editor_single', [
          'nodehive_space' => $space->id(),
        ], [
          'query' => ['url' => $frontend_url],
        ])->toString();

        $icons .= '<a href="' . $ve_url . '" class="' . $icon_class . '" title="' . $this->t('Visual Editor') . '">'
          . '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg>'
          . '</a>';
      }
    }

    // Edit icon.
    $edit_url = $node->toUrl('edit-form')->toString();
    $icons .= '<a href="' . $edit_url . '" class="' . $icon_class . '" title="' . $this->t('Edit') . '">'
      . '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path></svg>'
      . '</a>';

    // External link icon.
    if ($frontend_url) {
      $open_label = (string) $this->t('Open on website');
      $icons .= '<a href="' . $frontend_url . '" class="' . $icon_class . '" title="' . $open_label . '" target="_blank">'
        . '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg>'
        . '</a>';
    }

    return '<div class="activity-actions">' . $icons . '</div>';
  }

  /**
   * Builds a link for a node.
   */
  protected function buildNodeLink($node) {
    $node_url = Url::fromRoute('entity.node.canonical', ['node' => $node->id()]);
    $node_link = Link::fromTextAndUrl($node->label(), $node_url)->toString();
    return $node_link;
  }

  /**
   * Builds a status for a node.
   */
  protected function buildNodeStatus($node) {
    $status_class = $node->isPublished() ? "published" : "unpublished";
    $status = $node->isPublished() ? $this->t('Published') : $this->t('Unpublished');

    $markup = "<span class='marker marker--" . strtolower($status_class) . "'>$status</span>";
    return $markup;
  }

  /**
   * Builds a language switcher for a node.
   */
  protected function buildLanguageSwitcher($entity) {
    return $this->languageHelper->buildLanguageEditLinks($entity);
  }

  /**
   * Builds a link for a node.
   */
  protected function buildLink($node, $type = 'view') {
    $route = ($type === 'edit') ? 'entity.node.edit_form' : 'entity.node.canonical';

    $link = [
      '#type' => 'link',
      '#url' => Url::fromRoute($route, ['node' => $node->id()]),
      '#title' => ucfirst($type),
      '#attributes' => [
        'class' => ['button', 'button--small'],
      ],
    ];

    $link = $this->renderer->renderRoot($link);

    return $link;
  }

  /**
   * Gets the workflow state for a node.
   */
  protected function getWorkflowState($node, $workflow) {
    $state = '';
    if ($node->hasField('moderation_state') && !$node->get('moderation_state')->isEmpty()) {
      $workflow = $this->entityTypeManager->getStorage('workflow')->load($workflow);
      $state_plugin = $workflow ? $workflow->getTypePlugin()->getState($node->get('moderation_state')->value) : NULL;
      $state = $state_plugin ? $state_plugin->label() : '';
    }

    $markup = "<span class='marker marker--" . strtolower($state) . "'>$state</span>";
    return $markup;
  }

  /**
   * Gets the author's name for a node.
   */
  protected function getAuthorName(NodeInterface $node) {
    $author_name = '';
    $max_length = 14;

    if ($node->hasField('uid') && !$node->get('uid')->isEmpty()) {
      $author = $this->entityTypeManager->getStorage('user')->load($node->get('uid')->target_id);
      if ($author) {
        $full_name = $author->getDisplayName();
        if (mb_strlen($full_name) > $max_length) {
          $author_name = mb_substr($full_name, 0, $max_length) . '...';
        }
        else {
          $author_name = $full_name;
        }
      }
    }

    $link = [
      '#type' => 'link',
      '#url' => $node->getOwner()->toUrl(),
      '#title' => $author_name,
      '#attributes' => [
        'class' => ['username'],
      ],
    ];

    $link = $this->renderer->renderRoot($link);

    return $link;
  }

  /**
   * Gets the space link for a node.
   */
  protected function getSpaceLink($node) {
    if ($node->hasField('nodehive_space') && !$node->get('nodehive_space')->isEmpty()) {
      $space = $this->entityTypeManager->getStorage('nodehive_space')->load($node->get('nodehive_space')->target_id);
      if ($space) {
        $link = Link::fromTextAndUrl($space->label(), Url::fromRoute('entity.nodehive_space.canonical', ['nodehive_space' => $space->id()]));
        $link_render = $link->toRenderable();
        $link_render['#attributes']['class'] = ['truncate', 'text-ellipsis', 'block', 'max-w-36'];
        return $this->renderer->renderRoot($link_render);
      }
      return $this->t('not set');
    }
    return $this->t('not set');
  }

  /**
   * Retrieves nodes assigned to the current user.
   */
  protected function getAssignedToMeContent($number_of_items) {
    return $this->loadNodes($number_of_items, ['uid' => $this->currentUser->id()]);
  }

  /**
   * Retrieves team nodes.
   */
  protected function getTeamContent($number_of_items) {
    return $this->loadNodes($number_of_items);
  }

  /**
   * Loads nodes with optional conditions.
   */
  protected function loadNodes($number_of_items, array $conditions = []) {
    $query = $this->entityTypeManager->getStorage('node')->getQuery()->accessCheck(TRUE)->sort('changed', 'DESC')->range(0, $number_of_items);

    // Get all spaces that the current user has access.
    $spaces_query = $this->entityTypeManager
      ->getStorage('nodehive_space')
      ->getQuery()
      ->accessCheck(TRUE);
    $spaces_id = $spaces_query->execute();

    // If user has no spaces, return empty result.
    if (empty($spaces_id)) {
      return [];
    }

    // Show nodes from user's spaces.
    $query->condition("nodehive_space", $spaces_id, "IN");

    foreach ($conditions as $field => $value) {
      $query->condition($field, $value);
    }
    return $this->entityTypeManager->getStorage('node')->loadMultiple($query->execute());
  }

}
