<?php
declare(strict_types=1);

namespace PpPhp\Core\Platform\Event\Worker\Pool;

use PpPhp\Core\Platform\Event\Worker\DispatcherWorkerAdapter;

final class WorkerPoolManager
{
    private static ?self $instance = null;

    private WorkerPool $pool;
    private WorkerPoolStore $store;

    private function __construct(private readonly string $basePath)
    {
        $this->pool = new WorkerPool();
        $this->store = new WorkerPoolStore($basePath);
    }

    public static function instance(?string $basePath = null): self
    {
        if (self::$instance === null) {
            $basePath ??= self::detectBasePath();
            self::$instance = new self($basePath);
        }
        return self::$instance;
    }

    public static function resetInstance(?string $basePath = null): self
    {
        $basePath ??= self::detectBasePath();
        self::$instance = new self($basePath);
        return self::$instance;
    }

    public function pool(): WorkerPool { return $this->pool; }
    public function store(): WorkerPoolStore { return $this->store; }

    public function ensureDefaultPool(int $workers = 3): void
    {
        if ($this->pool->registry()->count() > 0) {
            return;
        }

        for ($i = 1; $i <= $workers; $i++) {
            $id = 'worker_pool_' . str_pad((string) $i, 3, '0', STR_PAD_LEFT);
            $this->pool->register(new DispatcherWorkerAdapter($id, 'pool-worker-' . $i));
        }
    }

    public function save(): WorkerPoolSnapshot
    {
        return $this->store->save($this->pool);
    }

    public function load(): WorkerPoolSnapshot
    {
        return $this->store->load();
    }

    public function hydrate(): void
    {
        $snapshot = $this->load();
        if ($snapshot->workers() !== []) {
            $this->pool->restore($snapshot);
        }
    }

    public function clear(): void
    {
        $this->pool = new WorkerPool();
        $this->store->reset();
    }

    public function summary(): array
    {
        if ($this->pool->registry()->count() === 0 && $this->store->exists()) {
            $this->hydrate();
        }

        return [
            'pool' => $this->pool->toArray(),
            'persisted' => $this->store->exists(),
            'stateFile' => $this->store->stateFile(),
        ];
    }

    private static function detectBasePath(): string
    {
        $candidate = dirname(__DIR__, 5);
        $real = realpath($candidate);
        return $real !== false ? $real : $candidate;
    }
}
