<?php
declare(strict_types=1);

namespace PpPhp\Core\Platform\Event\Scheduler;

use PpPhp\Core\Platform\Event\Queue\DeferredQueueManager;
use PpPhp\Core\Platform\Event\Scheduler\Runtime\SchedulerExecutor;
use PpPhp\Core\Platform\Event\Scheduler\Runtime\SchedulerRepository;

final class SchedulerRuntime
{
    public function __construct(
        private readonly SchedulerRepository $repository = new SchedulerRepository(),
        private readonly DeferredQueueManager $queue = new DeferredQueueManager(),
        private readonly SchedulerClock $clock = new SchedulerClock()
    ) {}

    public function repository(): SchedulerRepository { return $this->repository; }
    public function queue(): DeferredQueueManager { return $this->queue; }

    public function run(?callable $handler = null): int
    {
        $count = 0;
        $executor = new SchedulerExecutor($this->queue, $this->clock);

        foreach ($this->repository->due($this->clock->now()->format(DATE_ATOM)) as $event) {
            $result = $executor->execute($event);
            $this->repository->replace($result);
            $count++;
        }

        if ($handler !== null) {
            $this->queue->flush($handler);
        }

        return $count;
    }

    public function statistics(): SchedulerStatistics
    {
        return new SchedulerStatistics(
            $this->repository->countByState(ScheduleState::PENDING),
            $this->repository->countByState(ScheduleState::COMPLETED),
            $this->repository->countByState(ScheduleState::CANCELLED),
            $this->repository->countByState(ScheduleState::FAILED)
        );
    }
}
