<?php

namespace Drupal\social_auth_vk\OAuth2\Client\Provider;

use League\OAuth2\Client\Provider\AbstractProvider;
use League\OAuth2\Client\Token\AccessToken;
use Psr\Http\Message\ResponseInterface;
use VK\Client\VKApiClient;
use VK\OAuth\VKOAuth;

/**
 * Custom provider to use official sdk.
 */
class VkSdkDecorator extends AbstractProvider {

  public const ACCESS_TOKEN_RESOURCE_OWNER_ID = 'user_id';

  /**
   * OAuth from SDK.
   *
   * @var \VK\OAuth\VKOAuth
   */
  protected VKOAuth $oauth;

  /**
   * API client from SDK.
   *
   * @var \VK\Client\VKApiClient
   */
  protected VKApiClient $apiClient;

  /**
   * {@inheritDoc}
   */
  public function __construct(array $options = [], array $collaborators = []) {
    parent::__construct($options, $collaborators);

    $this->oauth = new VKOAuth();
    $this->apiClient = new VKApiClient();
  }

  /**
   * {@inheritDoc}
   */
  public function getAuthorizationUrl(array $options = []): string {
    if (empty($options['state'])) {
      $options['state'] = $this->getRandomState();
      $this->state = $options['state'];
    }

    return $this->oauth->getAuthorizeUrl(
      $options['response_type'],
      $this->clientId,
      $this->redirectUri,
      $options['display'],
      $options['scope'],
      $options['state']
    );
  }

  /**
   * {@inheritDoc}
   */
  public function getAccessToken($grant, array $options = []): AccessToken {
    $response = $this->oauth->getAccessToken($this->clientId, $this->clientSecret, $this->redirectUri, $options['code']);
    $response['resource_owner_id'] = $response['user_id'];

    return new AccessToken($response);
  }

  /**
   * {@inheritDoc}
   */
  protected function fetchResourceOwnerDetails(AccessToken $token) {
    $response = $this->apiClient->users()->get($token->getToken(), [
      'user_ids' => [$token->getResourceOwnerId()],
      'fields' => ['email', 'first_name', 'last_name', 'photo_max_orig'],
    ]);

    return reset($response);
  }

  /**
   * {@inheritDoc}
   */
  protected function createResourceOwner(array $response, AccessToken $token) {
    $values = $token->getValues();
    if (isset($values['email'])) {
      $response['email'] = $values['email'];
    }

    return new VkUser($response);
  }

  /**
   * {@inheritDoc}
   */
  public function getBaseAuthorizationUrl() {
    throw new \BadMethodCallException('Not implemented/used');
  }

  /**
   * {@inheritDoc}
   */
  public function getBaseAccessTokenUrl(array $params) {
    throw new \BadMethodCallException('Not implemented/used');
  }

  /**
   * {@inheritDoc}
   */
  public function getResourceOwnerDetailsUrl(AccessToken $token) {
    throw new \BadMethodCallException('Not implemented/used');
  }

  /**
   * {@inheritDoc}
   */
  protected function getDefaultScopes() {
    throw new \BadMethodCallException('Not implemented/used');
  }

  /**
   * {@inheritDoc}
   */
  protected function checkResponse(ResponseInterface $response, $data) {
    throw new \BadMethodCallException('Not implemented/used');
  }

}
