<?php

namespace Velis\Test\Db;

use ArrayObject;
use Exception;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use ReflectionException;
use Sharehouse\Lease;
use Sharehouse\Repository\LeaseRepository;
use Velis\Bpm\Ticket\Ticket;
use Velis\Db\Db;
use Velis\Db\EntityRepository;
use Velis\Db\Exception as DbException;
use Velis\Model\DataObject;

class DbTest extends TestCase
{
    private Db&MockObject $db;

    protected function setUp(): void
    {
        $this->db = $this->getMockForAbstractClass(Db::class);
    }

    /**
     * @param class-string<DataObject> $entityClass
     * @param class-string<EntityRepository> $expectedRepositoryClass
     * @throws ReflectionException
     *
     * @dataProvider provideTestDataForGetRepositoryMethod
     */
    public function testGetRepository(string $entityClass, string $expectedRepositoryClass)
    {
        $actualRepository = $this->db->getRepository($entityClass);

        $this->assertInstanceOf($expectedRepositoryClass, $actualRepository);
    }

    /**
     * @return array<array{0: class-string<DataObject>, 1: class-string<EntityRepository>}>
     */
    public function provideTestDataForGetRepositoryMethod(): array
    {
        return [
            [Ticket::class, EntityRepository::class],
            [Lease::class, LeaseRepository::class],
        ];
    }

    /**
     * @param class-string $entityClass
     * @param class-string<Exception> $expectedException
     * @throws ReflectionException
     *
     * @dataProvider provideTestDataForGetRepositoryMethodWhenRepositoryDoesNotExist
     */
    public function testGetRepositoryWhenRepositoryDoesNotExist(string $entityClass, string $expectedException)
    {
        $this->expectException($expectedException);
        $this->db->getRepository($entityClass);
    }

    /**
     * @return array<array{0: class-string, 1: class-string<Exception>}>
     */
    public function provideTestDataForGetRepositoryMethodWhenRepositoryDoesNotExist(): array
    {
        return [
            [ArrayObject::class, DbException::class],
            ['\Class\That\Does\Not\Exist', DbException::class],
        ];
    }
}
