<?php
declare(strict_types=1);

namespace PpPhp\Core\Platform\Event\Scheduler\Runtime;

use PpPhp\Core\Platform\Event\Scheduler\ScheduledEvent;
use PpPhp\Core\Platform\Event\Scheduler\SchedulerSnapshot;
use PpPhp\Core\Platform\Event\Scheduler\ScheduleState;

final class SchedulerRepository
{
    private array $events = [];

    public function add(ScheduledEvent $event): void { $this->events[$event->id()] = $event; }
    public function get(string $id): ?ScheduledEvent { return $this->events[$id] ?? null; }
    public function remove(string $id): bool
    {
        if (!isset($this->events[$id])) { return false; }
        unset($this->events[$id]);
        return true;
    }

    public function all(): array { return array_values($this->events); }

    public function due(?string $now = null): array
    {
        return array_values(array_filter($this->events, static fn (ScheduledEvent $event): bool => $event->state() === ScheduleState::PENDING && $event->isDue($now)));
    }

    public function replace(ScheduledEvent $event): void { $this->events[$event->id()] = $event; }
    public function clear(): void { $this->events = []; }

    public function snapshot(): SchedulerSnapshot
    {
        return new SchedulerSnapshot(array_map(static fn (ScheduledEvent $event): array => $event->toArray(), $this->all()));
    }

    public function restore(SchedulerSnapshot $snapshot): void
    {
        $this->events = [];
        foreach ($snapshot->events() as $row) {
            $event = ScheduledEvent::fromArray($row);
            $this->events[$event->id()] = $event;
        }
    }

    public function countByState(string $state): int
    {
        return count(array_filter($this->events, static fn (ScheduledEvent $event): bool => $event->state() === $state));
    }
}
