<?php
declare(strict_types=1);

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

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

    private WorkerStaleStore $store;
    private WorkerStaleDetector $detector;

    private function __construct(private readonly string $basePath, ?WorkerStalePolicy $policy = null)
    {
        $this->store = new WorkerStaleStore($basePath);
        $this->detector = new WorkerStaleDetector($policy ?? WorkerStalePolicy::default());
    }

    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, ?WorkerStalePolicy $policy = null): self
    {
        $basePath ??= self::detectBasePath();
        self::$instance = new self($basePath, $policy);

        return self::$instance;
    }

    public function inspect(?WorkerHeartbeatCollection $heartbeats = null, array $expectedWorkerIds = []): WorkerStaleReport
    {
        if ($heartbeats === null) {
            $heartbeatManager = WorkerHeartbeatManager::instance($this->basePath);
            $heartbeatManager->hydrate();
            $heartbeats = $heartbeatManager->collection();
        }

        $report = $this->detector->inspect($heartbeats, $expectedWorkerIds);
        $this->store->save($report);

        return $report;
    }

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

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

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

    public function summary(): array
    {
        $report = $this->store->exists() ? $this->load() : $this->inspect();

        return [
            'records' => $report->records(),
            'statistics' => $report->statistics(),
            'policy' => $report->policy(),
            '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;
    }
}
