<?php

namespace Velis\Test\Repository\Bpm\Ticket;

use PHPUnit\Framework\TestCase;
use ReflectionException;
use Velis\App;
use Velis\Db\Db;
use Velis\Exception\WrongTicketTypeException;

class TicketRepositoryTest extends TestCase
{
    private Db $db;

    protected function setUp(): void
    {
        $this->db = App::getService('db');
    }

    /**
     * @param class-string $entityClass
     * @throws ReflectionException
     *
     * @dataProvider provideMismatchedTypes
     */
    public function testFindMismatchedTypes(string $entityClass, int $id): void
    {
        $this->expectException(WrongTicketTypeException::class);

        $repository = $this->db->getRepository($entityClass);
        $repository->find($id);
    }

    /**
     * @return array<array{0: class-string, 1: int}>
     */
    public function provideMismatchedTypes(): array
    {
        $types = [
            'Building',
            'Inspection',
            'Cia',
        ];

        /** @var Db $db */
        $db = App::getService('db');

        $result = [];

        foreach ($types as $type) {
            $mismatchedId = $db->getOne('
                SELECT ticket_id
                FROM app.ticket_tab
                WHERE ticket_type_id <> :type
                LIMIT 1
            ', [
                'type' => $type,
            ]);

            $result[] = [sprintf('%s\Ticket', $type), $mismatchedId];
        }

        return $result;
    }

    /**
     * @param class-string $entityClass
     * @throws ReflectionException
     *
     * @dataProvider provideMatchingTypes
     */
    public function testFindMatchingTypes(string $entityClass, int $id): void
    {
        $repository = $this->db->getRepository($entityClass);
        $ticket = $repository->find($id);

        $this->assertInstanceOf($entityClass, $ticket);
        $this->assertNotNull($ticket['title']);
        $this->assertNotNull($ticket['ticket_status_id']);
    }

    /**
     * @return array<array{0: class-string, 1: int}>
     */
    public function provideMatchingTypes(): array
    {
        $types = [
            'Building',
            'Inspection',
            'Cia',
        ];

        /** @var Db $db */
        $db = App::getService('db');

        $result = [];

        foreach ($types as $type) {
            $matchingId = $db->getOne('
                SELECT ticket_id
                FROM app.ticket_tab
                WHERE ticket_type_id = :type
                LIMIT 1
            ', [
                'type' => $type,
            ]);

            $result[] = [sprintf('%s\Ticket', $type), $matchingId];
        }

        return $result;
    }

    /**
     * @param class-string $entityClass
     * @throws ReflectionException
     *
     * @dataProvider provideTypes
     */
    public function testFindBy(string $entityClass): void
    {
        $repository = $this->db->getRepository($entityClass);
        $entities = $repository->findBy([], null, 5);

        $this->assertContainsOnlyInstancesOf($entityClass, $entities);
    }

    /**
     * @return array<array<class-string>>
     */
    public function provideTypes(): array
    {
        return [
            ['Building\Ticket'],
            ['Inspection\Ticket'],
            ['Cia\Ticket'],
        ];
    }
}
