<?php
/**
 * BookiFlex Core
 *
 * @package    BookiFlex
 * @subpackage Core
 * @author     BookiFlex
 * @copyright  Copyright (c) 2025 BookiFlex
 * @license    GPL-2.0-or-later
 *
 * @link       https://bookiflex.com
 */

declare(strict_types=1);

namespace BookiFlex\Core\Infrastructure\Storage\WordPress;

use BookiFlex\Core\Infrastructure\Storage\CacheRepositoryInterface;

defined( 'ABSPATH' ) || exit;

/**
 * WordPress implementation of cache repository.
 *
 * Wraps WordPress transients API with automatic key prefixing.
 */
final class WordPressCacheRepository implements CacheRepositoryInterface
{
    /**
     * @param string $prefix Prefix for all cache keys
     */
    public function __construct(
        private readonly string $prefix
    ) {
    }

    /**
     * {@inheritDoc}
     */
    public function get(string $key, mixed $default = null): mixed
    {
        $value = get_transient($this->prefixKey($key));

        return $value === false ? $default : $value;
    }

    /**
     * {@inheritDoc}
     */
    public function set(string $key, mixed $value, int $ttl = 3600): bool
    {
        return set_transient($this->prefixKey($key), $value, $ttl);
    }

    /**
     * {@inheritDoc}
     */
    public function delete(string $key): bool
    {
        return delete_transient($this->prefixKey($key));
    }

    /**
     * {@inheritDoc}
     */
    public function has(string $key): bool
    {
        return get_transient($this->prefixKey($key)) !== false;
    }

    /**
     * {@inheritDoc}
     */
    public function flush(): bool
    {
        global $wpdb;

        // Delete all transients with our prefix
        $prefix = $wpdb->esc_like('_transient_' . $this->prefix) . '%';
        $timeoutPrefix = $wpdb->esc_like('_transient_timeout_' . $this->prefix) . '%';

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $deleted = $wpdb->query(
            $wpdb->prepare(
                "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s",
                $prefix,
                $timeoutPrefix
            )
        );

        return $deleted !== false;
    }

    /**
     * Add prefix to cache key.
     *
     * @param string $key Original key
     * @return string Prefixed key
     */
    private function prefixKey(string $key): string
    {
        return $this->prefix . $key;
    }
}
