<?php

namespace Drupal\castorcito\Controller;

use Drupal\castorcito\CastorcitoComponentInterface;
use Drupal\castorcito\CastorcitoManager;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Database\Connection;
use Drupal\Core\Url;
use Drupal\system\SystemManager;
use Drupal\Component\Render\FormattableMarkup;
use Symfony\Component\DependencyInjection\ContainerInterface;



/**
 * Returns responses for CastorcitoController.
 */
class CastorcitoController extends ControllerBase {

  /**
   * System Manager Service.
   *
   * @var \Drupal\system\SystemManager
   */
  protected $systemManager;

  /**
   * The current component.
   *
   * @var \Drupal\castorcito\CastorcitoComponentInterface
   */
  protected $component;

  /**
   * Castorcito Manager Service.
   *
   * @var \Drupal\castorcito\CastorcitoManager
   */
  protected $castorcitoManager;

  /**
   * The current database connection.
   *
   * @var Drupal\Core\Database\Connection
   */
  protected $connection;

  /**
   * Constructs a new CastorcitoController.
   *
   * @param \Drupal\system\SystemManager $systemManager
   *   System manager service.
   * @param \Drupal\castorcito\CastorcitoManager $castorcitoManager
   *   Castorcito manager service.
   * @param Drupal\Core\Database\Connection $connection
   *   The current database connection.
   */
  public function __construct(
    SystemManager $systemManager,
    CastorcitoManager $castorcitoManager,
    Connection $connection
  ) {
    $this->systemManager = $systemManager;
    $this->castorcitoManager = $castorcitoManager;
    $this->connection = $connection;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('system.manager'),
      $container->get('castorcito.manager'),
      $container->get('database')
    );
  }

  /**
   * Renders the admin menu block content.
   *
   * @return array
   *   The render array of the admin menu block.
   */
  public function castorcitoAdminMenuBlockPage() {
    return $this->systemManager->getBlockContents();
  }

  /**
   * Displays the json model or configuration.
   */
  public function viewJson(CastorcitoComponentInterface $castorcito_component) {
    $this->component = $castorcito_component;
    $json = $this->component->get('model');

    return [
      '#theme' => 'castorcito_view_json',
      '#json' => $json,
      '#attached' => [
        'library' => [
          'castorcito/castorcito.admin',
        ],
      ],
    ];
  }

  /**
   * Displays link to show content where use component.
   *
   * @param $castorcito_component
   *
   * @return array
   */
  public function inUseModal($castorcito_component) {
    $list = $this->listUsedComponentsModal($castorcito_component);

    $info = [];

    foreach ($list as $entity_type => $entities) {
      if (!isset($entities['entities'])) {
        continue;
      }

      $rows_data = [];
      foreach ($entities['entities'] as $entity) {
        $rows_data[] = [
          [
            'data' => new FormattableMarkup(
              '<a href=":link" target="_blank">@label</a>',
              [
                ':link' => $entity['link'],
                '@label' => $entity['label'],
              ]
            ),
          ],
        ];
      }

      $link = [];
      if ($entities['show_link']) {
        $link = [
          '#type' => 'link',
          '#title' => $this->t('View all entities'),
          '#url' => Url::fromRoute('entity.castorcito_component.inuse_page', [
            'entity_type' => $entity_type,
            'castorcito_component' => $castorcito_component
          ]),
          '#attributes' => [
            'class' => ['button', 'button--primary'],
            'target' => '_blank',
          ],
        ];
      }

      $info[] = [
        '#type' => 'details',
        '#open' => TRUE,
        '#title' => $entities['label'] . ' (' . $entities['total'] .')' ?? ucfirst($entity_type),
        'table' => [
          '#type' => 'table',
          '#header' => [],
          '#rows' => $rows_data,
        ],
        'link' => $link,
      ];
    }

    return $info;
  }

  /**
   * Function to validate if component is usage.
   *
   * @param string $component_id
   * @return array $list
   */
  protected function listUsedComponentsModal(string $component_id): array {
    $list = [];
    $json_fields = $this->entityTypeManager()->getStorage('field_storage_config')->loadByProperties([
      'module' => 'json_field',
    ]);

    $query_parts = [];
    foreach ($json_fields as $field) {
      $entity_type = $field->getTargetEntityTypeId();
      $entity_type_definition = $this->entityTypeManager->getDefinition($entity_type);
      $table = $entity_type . '__' . $field->getName();
      $column = $field->getName() . '_value';
      $query_parts[$entity_type][] = "SELECT entity_id, bundle FROM {$table} WHERE {$column} LIKE :like_value";
    }

    $final_queries = [];
    foreach ($query_parts as $entity_type => $queries) {
      $sql = implode(' UNION ', $queries);
      $final_sql = "SELECT * FROM ({$sql}) AS subquery";
      $final_sql .= " ORDER BY entity_id ASC LIMIT 20 OFFSET 0";
      $final_queries[$entity_type] = $final_sql;
    }

    $args = [
      ':like_value' => '%' . $this->connection->escapeLike($component_id) . '%',
    ];

    foreach ($final_queries as $entity_type => $sql) {
      $entity_type_definition = $this->entityTypeManager->getDefinition($entity_type);

      $count_sql = "SELECT COUNT(*) FROM ({$sql}) AS subquery";
      $total = $this->connection->query($count_sql, $args)->fetchField();

      $results = $this->connection->query($sql, $args)->fetchAll();

      $list[$entity_type]['label'] = $entity_type_definition->getBundleLabel();
      $list[$entity_type]['total'] = $total;
      $list[$entity_type]['show_link'] = FALSE;
      if (count($results) == 20) {
        $list[$entity_type]['show_link'] = TRUE;
      }

      $entity_ids = array_column($results, 'entity_id');
      $entities = $this->entityTypeManager->getStorage($entity_type)->loadMultiple($entity_ids);
      foreach ($results as $row) {
        $entity = $entities[$row->entity_id] ?? NULL;
        if ($entity) {
          $list[$entity_type]['entities'][$row->entity_id] = [
            'label' => $entity->label(),
            'link' => $entity->toUrl('edit-form')->toString(),
          ];
        }
      }
    }

    return $list;
  }

  /**
   * Provides a generic title callback for a in use entity.
   *
   * @param $castorcito_component
   *
   * @return string|null
   *   The title for the entity in use page, if an entity was found.
   */
  public function inUseTitle($castorcito_component) {
    $component = $this->castorcitoManager->castorcitoComponent($castorcito_component);
    return $this->t('In use: %entity', ['%entity' => $component->label()]);
  }

}
