<?php

namespace Db\EntityHook;

use Phalcon\Di\DiInterface;
use PHPUnit\Framework\TestCase;
use Velis\Db\EntityHook\EntityHookExecutor;
use Velis\Db\EntityHook\EventType;
use Velis\Db\EntityHook\HasHook;
use Velis\Model\DataObject;

class EntityHookExecutorTest extends TestCase
{
    /**
     * @dataProvider provideExecuteHooks
     */
    public function testExecuteHooks(EventType $event, int $expectedHookCalls): void
    {
        $hook = $this->createMock(ExampleHook::class);
        $hook->expects($this->exactly($expectedHookCalls))
            ->method('execute')
            ->with($this->isInstanceOf(ExampleDataObject::class));

        $di = $this->createMock(DiInterface::class);
        $di->expects($this->exactly($expectedHookCalls))
            ->method('get')
            ->willReturn($hook);

        $executor = new EntityHookExecutor($di);

        $object = new ExampleDataObject();

        $executor->executeHooks($event, $object);
    }

    /**
     * @return array<array{0: EventType, 1: int}>
     */
    public function provideExecuteHooks(): array
    {
        return [
            [EventType::PRE_PERSIST, 1],
            [EventType::POST_PERSIST, 0],
            [EventType::PRE_MERGE, 1],
            [EventType::POST_MERGE, 0],
            [EventType::PRE_REMOVE, 0],
            [EventType::POST_REMOVE, 0],
        ];
    }
}

// phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
// the classes below are created only for this test
#[HasHook(EventType::PRE_PERSIST, ExampleHook::class, 'execute')]
class ExampleDataObject extends BaseExampleDataObject
{
}

#[HasHook(EventType::PRE_MERGE, ExampleHook::class, 'execute')]
class BaseExampleDataObject extends DataObject
{
    protected function _getTableName(): string
    {
        return 'example_table';
    }
}

class ExampleHook
{
    public function execute(ExampleDataObject $object): void
    {
    }
}
