<?php

declare(strict_types=1);

namespace Flowaxy\Infrastructure\Persistence\Repositories;

use Flowaxy\Infrastructure\Persistence\Database\Database;
use Flowaxy\Support\Facades\Log;
use Throwable;

/**
 * Репозиторий для работы с capabilities плагинов
 *
 * @package Flowaxy\Infrastructure\Persistence\Repositories
 */
final class PluginCapabilityRepository
{
    public function __construct(
        private readonly Database $database
    ) {
    }

    /**
     * Проверить, имеет ли плагин capability
     *
     * @param string $pluginSlug Slug плагина
     * @param string $capability Название capability
     * @return bool
     */
    public function hasCapability(string $pluginSlug, string $capability): bool
    {
        try {
            $result = $this->database->query(
                "SELECT 1 FROM plugin_capabilities WHERE plugin_slug = ? AND capability = ? AND granted = 1",
                [$pluginSlug, $capability]
            );

            return is_array($result) && count($result) > 0;
        } catch (Throwable $e) {
            try {
                Log::Error('Ошибка проверки capability', [
                    'plugin_slug' => $pluginSlug,
                    'capability' => $capability,
                    'exception' => $e,
                ]);
            } catch (Throwable $logError) {
                // Ignore logging errors
            }
            return false;
        }
    }

    /**
     * Получить все granted capabilities для плагина
     *
     * @param string $pluginSlug Slug плагина
     * @return array<int, string>
     */
    public function getGrantedCapabilities(string $pluginSlug): array
    {
        try {
            $stmt = $this->database->query(
                "SELECT capability FROM plugin_capabilities WHERE plugin_slug = ? AND granted = 1",
                [$pluginSlug]
            );

            $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
            return array_column($result, 'capability');
        } catch (Throwable $e) {
            try {
                Log::Error('Ошибка получения capabilities', [
                    'plugin_slug' => $pluginSlug,
                    'exception' => $e,
                ]);
            } catch (Throwable $logError) {
                // Ignore logging errors
            }
            return [];
        }
    }

    /**
     * Предоставить capability плагину
     *
     * @param string $pluginSlug Slug плагина
     * @param string $capability Название capability
     * @return bool
     */
    public function grantCapability(string $pluginSlug, string $capability): bool
    {
        try {
            // Проверяем, существует ли запись
            $stmt = $this->database->query(
                "SELECT id FROM plugin_capabilities WHERE plugin_slug = ? AND capability = ?",
                [$pluginSlug, $capability]
            );

            $existing = $stmt->fetchAll(PDO::FETCH_ASSOC);
            if (count($existing) > 0) {
                // Обновляем существующую запись
                return $this->database->execute(
                    "UPDATE plugin_capabilities SET granted = 1 WHERE plugin_slug = ? AND capability = ?",
                    [$pluginSlug, $capability]
                ) !== false;
            }

            // Создаем новую запись
            return $this->database->execute(
                "INSERT INTO plugin_capabilities (plugin_slug, capability, granted) VALUES (?, ?, 1)",
                [$pluginSlug, $capability]
            ) !== false;
        } catch (Throwable $e) {
            try {
                Log::Error('Ошибка предоставления capability', [
                    'plugin_slug' => $pluginSlug,
                    'capability' => $capability,
                    'exception' => $e,
                ]);
            } catch (Throwable $logError) {
                // Ignore logging errors
            }
            return false;
        }
    }

    /**
     * Отозвать capability у плагина
     *
     * @param string $pluginSlug Slug плагина
     * @param string $capability Название capability
     * @return bool
     */
    public function revokeCapability(string $pluginSlug, string $capability): bool
    {
        try {
            return $this->database->execute(
                "UPDATE plugin_capabilities SET granted = 0 WHERE plugin_slug = ? AND capability = ?",
                [$pluginSlug, $capability]
            ) !== false;
        } catch (Throwable $e) {
            try {
                Log::Error('Ошибка отзыва capability', [
                    'plugin_slug' => $pluginSlug,
                    'capability' => $capability,
                    'exception' => $e,
                ]);
            } catch (Throwable $logError) {
                // Ignore logging errors
            }
            return false;
        }
    }
}
