<?php

namespace Drupal\author_field\Controller;

use Drupal\Component\Utility\Xss;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Controller\ControllerBase;
use GuzzleHttp\ClientInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;

/**
 * Fetches data through ORCID public API.
 *
 * Populates autocomplete author field.
 * Reference - https://info.orcid.org/documentation/api-tutorials/api-tutorial-searching-the-orcid-registry/
 */
class RestApiController extends ControllerBase {
  /**
   * The http client.
   */
  protected ClientInterface $httpClient;

  /**
   * The configuration factory service.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * Constructs a new CustomWidget object.
   */
  public function __construct(ConfigFactoryInterface $config_factory,
        ClientInterface $http_client) {
    $this->configFactory = $config_factory;
    $this->httpClient = $http_client;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container): static {
    return new static(
          $container->get('config.factory'),
          $container->get('http_client')
      );
  }

  /**
   * Fetches the specified number of the author from ORCID public API.
   *
   * @throws \GuzzleHttp\Exception\GuzzleException
   */
  public function handleOrcidAutocomplete(Request $request): JsonResponse {
    $results = [];
    $input = $request->query->get('q');

    if (!$input) {
      return new JsonResponse($results);
    }
    $input = Xss::filter($input);

    $config = $this->configFactory->getEditable('author_field.settings');
    // Get the 'author_api' value from the configuration.
    $max_orcids_to_display = $config->get('author_items_depth');
    // 0 - Sandbox
    // 1 - Production
    $api_type = $config->get('author_api');
    $params = '?q=' . $input .
          '&fl=orcid,given-names,family-name,email,current-institution-affiliation-name&start=0&rows=' .
          $max_orcids_to_display;
    if ($api_type == 0) {
      $orcid_url = $config->get('sandbox_orcid_url');
    }
    else {
      $orcid_url = $config->get('orcid_url');
    }

    $result = $this->httpClient->request('GET', $orcid_url . $params,
          ['headers' => ['Accept' => 'application/vnd.orcid+json']]);

    $json_string = (string) $result->getBody();
    $json = json_decode($json_string, TRUE);

    $no_of_results = (string) $json['num-found'];
    if ($no_of_results > $max_orcids_to_display) {
      $no_of_results = $max_orcids_to_display;
    }

    for ($x = 0; $x < $no_of_results; $x++) {
      $id = (string) $json['expanded-result'][$x]['orcid-id'];
      $given_name = (string) $json['expanded-result'][$x]['given-names'];
      $family_name = (string) $json['expanded-result'][$x]['family-names'];
      // Selects top 3 organization names to display.
      $org_name_sliced = array_slice($json['expanded-result'][$x]['institution-name'], 0, 3);
      $org_name = json_encode($org_name_sliced, JSON_PRETTY_PRINT);
      if (count($org_name_sliced) == 0) {
        $results[] = [
          'value' => $id,
          'label' => $given_name . ' ' . $family_name . ' | ' . $id,
        ];
      }
      else {
        $results[] = [
          'value' => $id,
          'label' => $given_name . ' ' . $family_name . ' | ' . $id . ' | ' . $org_name,
        ];
      }
    }

    return new JsonResponse($results);
  }

}
