<?php

namespace Openguru\OpenCartFramework\TeleCartPulse;

use JsonException;

class PayloadSigner
{
    private ?string $secret;

    public function __construct(?string $secret = null)
    {
        $this->secret = $secret;
    }

    /**
     * @throws PayloadSignException
     */
    public function sign(array $payload): string
    {
        $this->ensureSecretExists();
        $encoded = $this->encodeJson($payload);

        return hash_hmac('sha256', $encoded, $this->secret);
    }

    /**
     * @throws PayloadSignException
     */
    public function verify(string $signature, array $payload): bool
    {
        $this->ensureSecretExists();
        $encoded = $this->encodeJson($payload);
        $expected = hash_hmac('sha256', $encoded, $this->secret);

        return hash_equals($signature, $expected);
    }

    private function encodeJson(array $payload): string
    {
        try {
            return json_encode($payload, JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        } catch (JsonException $e) {
            throw new PayloadSignException('Could not encode JSON: ' . $e->getMessage(), 0, $e);
        }
    }

    private function ensureSecretExists(): void
    {
        if (! $this->secret) {
            throw new PayloadSignException('No secret provided');
        }
    }
}
