<?php
declare(strict_types=1);

namespace PpPhp\Core\Platform\Event\Manifest;

use PpPhp\Core\Platform\Event\Registry\EventListenerRegistry;

final class ManifestListenerLoader
{
    private array $warnings = [];

    public function load(EventListenerRegistry $registry, array $manifest, string $basePath = ''): int
    {
        $count = 0;
        $listeners = $manifest['events']['listeners'] ?? $manifest['listeners'] ?? [];

        if (!is_array($listeners)) {
            return 0;
        }

        foreach ($listeners as $definition) {
            if (!is_array($definition)) {
                continue;
            }

            $event = (string) ($definition['event'] ?? '');
            $listener = $definition['listener'] ?? null;
            $priority = (int) ($definition['priority'] ?? 0);

            if ($event === '' || !is_string($listener)) {
                $this->warnings[] = ['message' => 'Invalid manifest listener definition.', 'definition' => $definition];
                continue;
            }

            if (str_contains($listener, '::')) {
                [$class, $method] = explode('::', $listener, 2);
                if (class_exists($class) && method_exists($class, $method)) {
                    $registry->register($event, [$class, $method], $priority, $definition['tags'] ?? ['manifest'], [
                        'source' => 'manifest',
                    ]);
                    $count++;
                }
                continue;
            }

            if (class_exists($listener)) {
                $instance = new $listener();
                $callable = method_exists($instance, 'handle') ? [$instance, 'handle'] : $instance;
                if (is_callable($callable)) {
                    $registry->register($event, $callable, $priority, $definition['tags'] ?? ['manifest'], [
                        'source' => 'manifest',
                    ]);
                    $count++;
                }
            }
        }

        return $count;
    }

    public function warnings(): array
    {
        return $this->warnings;
    }
}
