<?php

namespace Drupal\user_provisioning\ProviderSpecific\APIHandler\UserAPIHandler;

use Drupal\Core\Config\ImmutableConfig;
use Drupal\user_provisioning\Helpers\moUserProvisioningLogger;
use Drupal\user_provisioning\ProviderSpecific\APIHandler\moAPIHandlerInterface;
use GuzzleHttp\Client;
use Psr\Http\Message\ResponseInterface;

/**
 * Handles SCIM API requests for user provisioning.
 */
class moUserSCIMAPIHandler implements moAPIHandlerInterface {

  /**
   * SCIM server base URL.
   *
   * @var string
   *   SCIM server base URL.
   */
  private string $serverUrl;

  /**
   * Bearer token for SCIM API calls.
   *
   * @var string
   *   SCIM bearer token.
   */
  private string $bearerToken;

  /**
   * HTTP client for outbound API calls.
   *
   * @var \GuzzleHttp\Client
   *   HTTP client instance.
   */
  private Client $httpClient;

  /**
   * Immutable SCIM configuration.
   *
   * @var \Drupal\Core\Config\ImmutableConfig
   *   Read-only configuration object.
   */
  private ImmutableConfig $config;

  /**
   * Logger for handler diagnostics.
   *
   * @var \Drupal\user_provisioning\Helpers\moUserProvisioningLogger
   *   Logger instance.
   */
  private moUserProvisioningLogger $moLogger;

  /**
   * Constructs the SCIM API handler.
   */
  public function __construct() {
    $this->config = \Drupal::config('user_provisioning.settings');
    $this->serverUrl = $this->config->get('mo_user_provisioning_scim_server_base_url');
    $this->bearerToken = $this->config->get('mo_user_provisioning_scim_server_bearer_token');
    $this->httpClient = \Drupal::httpClient();
    $this->moLogger = new moUserProvisioningLogger();
  }

  /**
   * Sends a GET request to the configured SCIM server.
   *
   * @param string $query
   *   Resource query string.
   *
   * @return \Psr\Http\Message\ResponseInterface
   *   The provider response object.
   *
   * @throws \Exception
   */
  public function get(string $query): ResponseInterface {
    $url = $this->getRequestUrl($query);
    $options = ['headers' => ['Authorization' => 'Bearer ' . $this->bearerToken]];

    $this->moLogger->addLog('Query url is ' . $url, __LINE__, __FUNCTION__, __FILE__);
    $this->moLogger->addFormattedLog($options, __LINE__, __FUNCTION__, __FILE__, 'The header for resource search request is:');
    try {
      return $this->httpClient->get($url, $options);
    }
    catch (\Exception $exception) {
      // 409 conflict should be handled through the catch statement.
      throw new \Exception($exception->getMessage(), $exception->getCode(), $exception);
    }
  }

  /**
   * Sends a POST request to the configured SCIM server.
   *
   * @param array $body
   *   Request body payload.
   *
   * @return \Psr\Http\Message\ResponseInterface
   *   The provider response object.
   *
   * @throws \Exception
   */
  public function post(array $body): ResponseInterface {

    $header = [
      'Accept' => 'application/json',
      'Authorization' => 'Bearer ' . $this->bearerToken,
      'Content-Type' => 'application/json',
    ];

    $url = $this->postRequestUrl();

    $options = [
      'headers' => $header,
      'body' => json_encode($body),
    ];

    $this->moLogger->addLog('Query url is ' . $url, __LINE__, __FUNCTION__, __FILE__);
    $this->moLogger->addFormattedLog($options, __LINE__, __FUNCTION__, __FILE__, 'The header and body for resource creation request is:');

    try {
      return $this->httpClient->request(
            'POST',
            $url,
            $options,
        );
    }
    catch (\Exception $exception) {
      throw new \Exception($exception->getMessage(), $exception->getCode(), $exception);
    }
  }

  /**
   * Returns the URL for SCIM GET requests.
   *
   * @return string
   *   The absolute GET request URL.
   */
  private function getRequestUrl($query): string {
    return rtrim($this->serverUrl, '/') . '/' . $query;
  }

  /**
   * Creates and returns the URL to make POST api call for user creation.
   *
   * @return string
   *   The absolute POST request URL.
   */
  private function postRequestUrl(): string {
    return rtrim($this->serverUrl, '/') . '/Users';
  }

  /**
   * {@inheritDoc}
   */
  public function put(array $body) {
    // @todo Implement put() method.
  }

  /**
   * {@inheritDoc}
   */
  public function patch(array $patch) {
    // @todo Implement patch() method.
  }

  /**
   * {@inheritDoc}
   */
  public function delete($resource_id) {
    // @todo Implement delete() method.
  }

  /**
   * {@inheritDoc}
   */
  public function deactivate(array $body) {
    // @todo Implement deactivate() method.
  }

}
