<?php
declare(strict_types=1);

namespace Help4BuilderSuite\Modules\EmailMarketing;

if (! defined('ABSPATH')) {
    exit;
}

final class TokenService
{
    private const OPTION = 'h4bs_email_marketing_secret';

    private string $secret = '';

    /**
     * @param array<int, scalar|null> $parts
     */
    public function sign(string $purpose, array $parts): string
    {
        $payload = $purpose . "\0" . implode("\0", array_map(static fn ($part): string => (string) $part, $parts));
        return hash_hmac('sha256', $payload, $this->secret());
    }

    /**
     * @param array<int, scalar|null> $parts
     */
    public function verify(string $token, string $purpose, array $parts): bool
    {
        if (! preg_match('/^[a-f0-9]{64}$/', $token)) {
            return false;
        }

        return hash_equals($this->sign($purpose, $parts), strtolower($token));
    }

    /**
     * @param array<int, scalar|null> $parts
     */
    public function fingerprint(array $parts): string
    {
        return $this->sign('fingerprint', $parts);
    }

    private function secret(): string
    {
        if ($this->secret !== '') {
            return $this->secret;
        }

        $saved = get_option(self::OPTION, '');
        if (is_string($saved) && strlen($saved) >= 32) {
            $this->secret = $saved;
            return $this->secret;
        }

        try {
            $secret = rtrim(strtr(base64_encode(random_bytes(48)), '+/', '-_'), '=');
        } catch (\Throwable $exception) {
            $secret = wp_generate_password(64, true, true);
        }

        if (! add_option(self::OPTION, $secret, '', false)) {
            $existing = get_option(self::OPTION, '');
            if (is_string($existing) && strlen($existing) >= 32) {
                $secret = $existing;
            }
        }

        $this->secret = $secret;
        return $this->secret;
    }
}
