<?php

namespace WPSN\Modules\IndexNow;

defined('ABSPATH') || exit;

/**
 * Stores the IndexNow key.
 *
 * The IndexNow key must be publicly accessible at /{key}.txt, but we still keep
 * it outside the main settings export/import to avoid accidental overwrites.
 */
final class IndexNowSecretsRepository
{
    private const OPTION_NAME = 'wpsn_indexnow_key';

    public function getKey(): string
    {
        $v = get_option(self::OPTION_NAME, '');
        $v = is_string($v) ? trim($v) : '';
        return $this->sanitizeKey($v);
    }

    public function hasKey(): bool
    {
        return $this->getKey() !== '';
    }

    public function setKey(string $key): void
    {
        $key = $this->sanitizeKey($key);
        if ($key === '') {
            return;
        }
        update_option(self::OPTION_NAME, $key, false);
    }

    public function clearKey(): void
    {
        delete_option(self::OPTION_NAME);
    }

    /**
     * Generate and persist a new key.
     */
    public function generateKey(): string
    {
        if (function_exists('wp_generate_uuid4')) {
            $key = (string) wp_generate_uuid4();
        } else {
            try {
                $key = bin2hex(random_bytes(16));
            } catch (\Throwable $e) {
                $key = uniqid('wpsn_', true);
            }
        }

        $this->setKey($key);
        return $this->getKey();
    }

    private function sanitizeKey(string $key): string
    {
        $key = trim($key);
        if ($key === '') {
            return '';
        }

        // Allow a-z, A-Z, 0-9 and dash (UUIDs).
        $san = preg_replace('/[^A-Za-z0-9\-]/', '', $key);
        if (!is_string($san)) {
            return '';
        }

        if (strlen($san) < 8) {
            return '';
        }

        if (strlen($san) > 128) {
            $san = substr($san, 0, 128);
        }

        return $san;
    }
}
