<?php declare(strict_types=1);
/**
 * @package messenger
 * @author kputyr
 * @date 17.04.2025
 */

namespace IMATHUZH\Messenger\Tests;

use IMATHUZH\Messenger\TouchPublisher;
use PHPUnit\Framework\TestCase;

/**
 * Replaces the actual touch action with the one that
 * registers the file to be touched and returns the
 * desired result of the action.
 */
class MockedTouchPublisher extends TouchPublisher
{
    /** The list of files on which the action fails */
    public $failing = [];

    /** The list of files on which the action was called */
    public $touched = [];

    /** The mocked action */
    protected function action(string $file): bool
    {
        $this->touched[] = $file;
        return !in_array($file, $this->failing);
    }
}


class TouchPublisherTest extends TestCase
{

    public static function fileProvider()
    {
        return [
            [ '/var/tmp',
                ['p_one', 'cmd_echo', 'msg_test', 'channel', 'pa_two'],
                ['/var/tmp/page/one', '/var/tmp/command/echo', '/var/tmp/page/admin/two']
            ],
            [ '/var/www/',
                ['p_one', 'cmd_echo', 'msg_test', 'channel', 'pa_two'],
                ['/var/www/page/one', '/var/www/command/echo', '/var/www/page/admin/two']
            ]
        ];
    }

    /**
     * @dataProvider fileProvider
     */
    public function testPublishMessage(string $rootDir, array $channels, array $files)
    {
        $publisher = new MockedTouchPublisher($rootDir, [
            'p' => 'page',
            'pa' => 'page/admin/',
            'cmd' => 'command'
        ]);
        $msg = 'some message';
        
        foreach($publisher->publishMessage($channels, $msg) as $error) { }
        $this->assertSame($files, $publisher->touched);
    }

    public function testFailedPublishMessage()
    {
        $publisher = new MockedTouchPublisher('/var/www/', [
            'p' => 'page',
            'pa' => 'page/admin/',
            'cmd' => 'command'
        ]);
        $msg = 'some message';

        $channels = ['p_one', 'message', 'cmd_some'];
        $failing = ['/var/www/page/one'];
        $publisher->failing = ['/var/www/page/one', '/var/www/page/some'];

        $errors = 0;
        foreach($publisher->publishMessage($channels, $msg) as $file => $error) {
            $this->assertContains($file, $failing);
            $errors++;
        }
        $this->assertEquals(1, $errors);
    }

}