<?php
/**
 * affilun Cloud request signer.
 *
 * @package Affilun\Application\Cloud
 */

declare(strict_types=1);

namespace Affilun\Application\Cloud;

use InvalidArgumentException;

/**
 * Creates HMAC headers for affilun Cloud API requests.
 */
final class CloudRequestSigner {

	/**
	 * Sign a request.
	 *
	 * @param string $siteId    affilun Cloud site id.
	 * @param string $apiKey    Site API key.
	 * @param string $method    HTTP method.
	 * @param string $path      Request path including query string.
	 * @param string $body      Raw request body.
	 * @param int    $timestamp Unix timestamp.
	 * @param string $nonce     Request nonce.
	 *
	 * @return array<string,string>
	 *
	 * @throws InvalidArgumentException When required values are missing.
	 */
	public function sign(
		string $siteId,
		string $apiKey,
		string $method,
		string $path,
		string $body,
		int $timestamp,
		string $nonce
	): array {
		$siteId = trim( $siteId );
		$apiKey = trim( $apiKey );
		$method = strtoupper( trim( $method ) );
		$path   = trim( $path );
		$nonce  = trim( $nonce );

		if ( $siteId === '' || $apiKey === '' || $method === '' || $path === '' || $nonce === '' ) {
			throw new InvalidArgumentException(
				'Cloud request signing requires site id, API key, method, path, and nonce.'
			);
		}
		if ( $timestamp <= 0 ) {
			throw new InvalidArgumentException( 'Cloud request timestamp must be positive.' );
		}

		$canonical = implode(
			"\n",
			array(
				$method,
				$path,
				(string) $timestamp,
				$nonce,
				hash( 'sha256', $body ),
			)
		);
		$signature = hash_hmac( 'sha256', $canonical, $apiKey );

		return array(
			'X-AFFILUN-Site-Id'   => $siteId,
			'X-AFFILUN-Timestamp' => (string) $timestamp,
			'X-AFFILUN-Nonce'     => $nonce,
			'X-AFFILUN-Signature' => $signature,
		);
	}
}
