<?php

/**
 * Fetches identity tokens.
 *
 * @package WooCommerce\PayPalCommerce\ApiClient\Endpoint
 */
declare (strict_types=1);
namespace WooCommerce\PayPalCommerce\ApiClient\Endpoint;

use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Token;
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WooCommerce\PayPalCommerce\Vendor\Psr\Log\LoggerInterface;
use WooCommerce\PayPalCommerce\ApiClient\Repository\CustomerRepository;
use WooCommerce\PayPalCommerce\Settings\Data\SettingsProvider;
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
/**
 * Class IdentityToken
 */
class IdentityToken
{
    use \WooCommerce\PayPalCommerce\ApiClient\Endpoint\RequestTrait;
    /**
     * The Bearer.
     *
     * @var Bearer
     */
    private $bearer;
    /**
     * The host.
     *
     * @var string
     */
    private $host;
    /**
     * The logger.
     *
     * @var LoggerInterface
     */
    private $logger;
    /**
     * The settings
     *
     * @var SettingsProvider
     */
    private $settings;
    /**
     * The customer repository.
     *
     * @var CustomerRepository
     */
    protected $customer_repository;
    /**
     * WooCommerce subscriptions mode.
     *
     * @var string
     */
    private string $subscription_mode;
    /**
     * IdentityToken constructor.
     *
     * @param string             $host The host.
     * @param Bearer             $bearer The bearer.
     * @param LoggerInterface    $logger The logger.
     * @param SettingsProvider   $settings The settings.
     * @param CustomerRepository $customer_repository The customer repository.
     * @param string             $subscription_mode WooCommerce subscriptions mode.
     */
    public function __construct(string $host, Bearer $bearer, LoggerInterface $logger, SettingsProvider $settings, CustomerRepository $customer_repository, string $subscription_mode)
    {
        $this->host = $host;
        $this->bearer = $bearer;
        $this->logger = $logger;
        $this->settings = $settings;
        $this->customer_repository = $customer_repository;
        $this->subscription_mode = $subscription_mode;
    }
    /**
     * Generates a token for a specific user.
     *
     * @param int $user_id The id of the user.
     *
     * @return Token
     * @throws RuntimeException If the request fails.
     */
    public function generate_for_user(int $user_id): Token
    {
        $bearer = $this->bearer->bearer();
        $url = trailingslashit($this->host) . 'v1/identity/generate-token';
        $args = array('method' => 'POST', 'headers' => array('Authorization' => 'Bearer ' . $bearer->token(), 'Content-Type' => 'application/json'));
        $vault_enabled = $this->settings->save_paypal_and_venmo();
        $vault_enabled_dcc = $this->settings->save_card_details();
        $subscriptions_mode_vaulting = $this->subscription_mode === SubscriptionHelper::SUBSCRIPTION_MODE_VALUE_VAULTING;
        if ($vault_enabled || $vault_enabled_dcc || $subscriptions_mode_vaulting) {
            $customer_id = $this->customer_repository->customer_id_for_user($user_id);
            update_user_meta($user_id, 'ppcp_customer_id', $customer_id);
            $args['body'] = wp_json_encode(array('customer_id' => $customer_id));
        }
        $response = $this->request($url, $args);
        if (is_wp_error($response)) {
            $error = new RuntimeException(__('Could not create identity token.', 'woocommerce-paypal-payments'));
            $this->logger->log('warning', $error->getMessage(), array('args' => $args, 'response' => $response));
            throw $error;
        }
        $json = json_decode($response['body']);
        $status_code = (int) wp_remote_retrieve_response_code($response);
        if (200 !== $status_code) {
            $error = new PayPalApiException($json, $status_code);
            $this->logger->log('warning', $error->getMessage(), array('args' => $args, 'response' => $response));
            throw $error;
        }
        $token = Token::from_json($response['body']);
        return $token;
    }
}