<?php

declare(strict_types=1);

namespace Plugin\tnt_stabila_shop\src\CronJobs;

use JTL\Cache\JTLCacheInterface;
use JTL\Cron\Job;
use JTL\Cron\JobHydrator;
use JTL\Cron\JobInterface;
use JTL\Cron\QueueEntry;
use JTL\DB\DbInterface;
use Plugin\tnt_stabila_shop\src\Repositories\DatabaseRepository;
use Plugin\tnt_stabila_shop\src\Repositories\SentrySpoolRepository;
use Plugin\tnt_stabila_shop\src\Services\SentrySpoolFlusher;
use Psr\Log\LoggerInterface;

/**
 * Sending-only cron: drains the Sentry spool out-of-band.
 *
 * Deliberately does ONE thing — replay spooled Sentry envelopes — so it can run on every cron
 * tick (frequency 0) without dragging along the housekeeping in {@see CronJob}. This is what
 * makes error delivery asynchronous: the shop request only ever writes to the spool table.
 */
class SentrySpoolCronJob extends Job
{
    public const CRON_JOB_ID      = 'tnt_stabila_sentry_spool';
    protected const CRON_JOB_NAME = 'Stabila Sentry Spool';
    /** 0 = run on every cron tick (like core's sendMailQueue), i.e. as often as cron fires. */
    protected const CRON_FREQUENCY = 0;

    public function __construct(
        DbInterface $db,
        LoggerInterface $logger,
        JobHydrator $hydrator,
        JTLCacheInterface $cache,
    ) {
        parent::__construct($db, $logger, $hydrator, $cache);
    }

    /**
     * @inheritdoc
     */
    public function start(QueueEntry $queueEntry): JobInterface
    {
        parent::start($queueEntry);

        $storedDsn = (new DatabaseRepository($this->db))->getSetting('sentryDsn');
        $flusher   = new SentrySpoolFlusher(
            new SentrySpoolRepository($this->db),
            \is_string($storedDsn) ? $storedDsn : ''
        );
        $delivered = $flusher->flush();
        $this->logger->debug(\sprintf('Stabila Sentry spool: delivered %d event(s)', $delivered));

        $this->setFinished(true);

        return $this;
    }

    /**
     * @return object{name: string, jobType: string, frequency: int, startDate: string, startTime: string}
     */
    public static function createCron(): object
    {
        return (object)[
            'name'      => self::CRON_JOB_NAME,
            'jobType'   => self::CRON_JOB_ID,
            'frequency' => self::CRON_FREQUENCY,
            'startDate' => 'NOW()',
            'startTime' => '00:00:00',
        ];
    }
}
