<?php
/**
 * EA Lab configuration repository.
 *
 * @package Ealab\Deployer
 */

namespace Ealab\Deployer\Utility\DeployerConfigRepository;

use Ealab\Deployer\Exception\EaLabWebServiceException;
use Ealab\Deployer\Exception\LicenceException;
use Ealab\Deployer\Exception\LicenceKeyUnsetException;
use Ealab\Deployer\Licence\LicenceManager;
use Ealab\Deployer\Utility\Settings;
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
use Throwable;

/**
 * EA Lab configuration repository.
 *
 * This provider fetches configuration from the EA Lab server.
 */
class EalabConfigRepository extends ConfigRepositoryBase {
	/**
	 * The licence status.
	 *
	 * @var array|null Licence status
	 */
	protected ?array $licenceStatus;

	/**
	 * {@inheritDoc}
	 */
	public function getConfig(): ?array {
		// Return cached config if available
		if ( $this->deployerConfig !== null ) {
			return $this->deployerConfig;
		}

		// Get the repository configuration.
		$http_client = new Client();

		try {
			$licence_key = LicenceManager::getInstance()->getLicenceKey();

			if ( empty( $licence_key ) ) {
				// No licence key.
				throw new LicenceKeyUnsetException( _dgettext( 'deployer-core', 'The licence key is not set.' ) );
			}

			// A GET request would have been better, but we need to send data through the request body
			// if we want to send the list of installed plugins. So POST is the only option for now.
			$response = $http_client->post(
				DEPLOY_SYNC_CONTENT__LICENCE_URL . '/api/v1/deployer/config',
				array(
					RequestOptions::HEADERS => array(
						'Content-Type'    => 'application/json',
						'X-EaLab-Api-Key' => $licence_key,
					),
					RequestOptions::JSON    => $this->getDefaultWebserviceRequestMetadata(),
				)
			);
		} catch ( LicenceKeyUnsetException $e ) {
			throw $e;
		} catch ( Throwable $e ) {
			if ( $e->getCode() === 403 ) {
				// The licence key is invalid.
				throw new LicenceException( _dgettext( 'deployer-core', 'The licence key is invalid.' ), 0, $e );
			}

			// i18n: Could not retrieve the config from the wp-deployer.io repository.
			throw new EaLabWebServiceException( _dgettext( 'deployer-core', 'Failed to reach the repository.' ), 0, $e );
		}

		$body    = $response->getBody()->getContents();
		$decoded = json_decode( $body, true );

		if ( json_last_error() !== JSON_ERROR_NONE ) {
			// i18n: The wp-deployer.io repository returned an invalid content.
			throw new EaLabWebServiceException( _dgettext( 'deployer-core', 'Failed to decode the repository config.' ) );
		}

		if ( ! is_array( $decoded ) || ! array_key_exists( 'deployerConfig', $decoded ) ) {
			throw new EaLabWebServiceException( _dgettext( 'deployer-core', 'The repository config is invalid.' ) );
		}

		$this->deployerConfig = $decoded['deployerConfig'];
		$this->licenceStatus  = $decoded['licenceStatus'];

		return $decoded;
	}

	/**
	 * Get the default metadata sent to the webservice.
	 *
	 * @return array<string,mixed> The metadata.
	 */
	private function getDefaultWebserviceRequestMetadata(): array {
		return array(
			'licence_metadata' => array(
				'product'     => array(
					'installedVersion' => DEPLOY_SYNC_CONTENT__VERSION,
				),
				'environment' => array(
					'prodUrl' => Settings::getInstance()->getProdUrl(),
					'id'      => get_site_url(),
				),
			),
		);
	}
}
