<?php

declare(strict_types=1);

namespace Flowaxy\Domain\Plugin\Services;

use Exception;
use Flowaxy\Domain\Events\DomainEventBridge;
use Flowaxy\Domain\Plugin\Entities\Plugin;
use Flowaxy\Domain\Plugin\Events\PluginInstalledEvent;
use Flowaxy\Support\Facades\Log;
use Throwable;

use function ucfirst;

// Сервіс встановлення плагіна
final class InstallPluginService
{
    public function __construct(private readonly PluginRepositoryInterface $plugins)
    {
    }

    public function execute(string $slug, array $config, ?callable $afterInstall = null): bool
    {
        if ($slug === '') {
            try {
                Log::Warning('Невалідний slug');
            } catch (Throwable $e) {
                // Ignore logging errors
            }
            return false;
        }

        $plugin = new Plugin(
            slug: $slug,
            name: $config['name'] ?? ucfirst($slug),
            version: $config['version'] ?? '1.0.0',
            active: false,
            description: $config['description'] ?? '',
            author: $config['author'] ?? '',
            meta: $config
        );

        $result = $this->plugins->install($plugin);

        if (!$result) {
            $exception = new Exception('PluginRepository::install returned false');
            try {
                Log::Error('Помилка встановлення плагіна', ['exception' => $exception]);
            } catch (Throwable $logError) {
                // Ignore logging errors
            }
            return false;
        }

        try {
            DomainEventBridge::dispatch(new PluginInstalledEvent(
                pluginSlug: $slug,
                version: $plugin->version
            ));
        } catch (Throwable $e) {
            // Ignore dispatch errors
        }

        if ($afterInstall !== null) {
            try {
                $afterInstall($plugin);
            } catch (Exception $e) {
                try {
                    Log::Error('Помилка виконання callback після встановлення плагіна', ['exception' => $e]);
                } catch (Throwable $logError) {
                    // Ignore logging errors
                }
            }
        }

        return $result;
    }
}
