<?php

declare(strict_types=1);

namespace Autogedal\FeedMonitor\Test\Unit\Model;

use Autogedal\FeedMonitor\Model\Adapter\SourceMonitorInterface;
use Autogedal\FeedMonitor\Model\Checker;
use Autogedal\FeedMonitor\Model\FeedMonitor;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;

/**
 * The periodic check goes through every source adapter; one failing source does not stop the others.
 */
class CheckerTest extends TestCase
{
    public function testStuckRunsThenEverySourceThenReminders(): void
    {
        $calls = [];
        $monitor = $this->createMock(FeedMonitor::class);
        $monitor->method('closeStuckRuns')->willReturnCallback(function () use (&$calls): array {
            $calls[] = 'stuck';
            return ['job_a: stuck'];
        });
        $monitor->method('remindOpenAlerts')->willReturnCallback(function () use (&$calls): void {
            $calls[] = 'remind';
        });

        $checker = new Checker($monitor, $this->createMock(LoggerInterface::class), [
            'custom_cron' => $this->source($calls, 'custom_cron', ['job_b: stale']),
            'magento_heartbeat' => $this->source($calls, 'magento_heartbeat', []),
        ]);

        self::assertSame(['job_a: stuck', 'job_b: stale'], $checker->run(true));
        self::assertSame(['stuck', 'custom_cron:1', 'magento_heartbeat:1', 'remind'], $calls);
    }

    public function testAFailingSourceIsReportedAndTheOthersStillRun(): void
    {
        $calls = [];
        $broken = $this->createMock(SourceMonitorInterface::class);
        $broken->method('check')->willThrowException(new \RuntimeException('db down'));
        $checker = new Checker($this->createMock(FeedMonitor::class), $this->createMock(LoggerInterface::class), [
            'broken' => $broken,
            'custom_subfeed' => $this->source($calls, 'custom_subfeed', []),
        ]);

        $found = $checker->run(false);

        self::assertSame(['Eroare la verificare (broken): db down'], $found);
        self::assertSame(['custom_subfeed:0'], $calls);
    }

    private function source(array &$calls, string $name, array $found): SourceMonitorInterface
    {
        $source = $this->createMock(SourceMonitorInterface::class);
        $source->method('check')->willReturnCallback(function (bool $outsideCron) use (&$calls, $name, $found): array {
            $calls[] = $name . ':' . (int)$outsideCron;
            return $found;
        });

        return $source;
    }
}
