<?php

declare(strict_types=1);

namespace Gls\GlsPoland\PrestaShop\ObjectModel\Repository;

use Doctrine\DBAL\Connection;
use Gls\GlsPoland\PrestaShop\ObjectModel\HydratorInterface;
use Gls\GlsPoland\PrestaShop\ObjectModel\Persistence;
use Gls\GlsPoland\PrestaShop\ObjectModel\PersistenceInterface;

/**
 * @extends AbstractMultiLangObjectModelRepository<\Tab>
 */
final class TabRepository extends AbstractMultiLangObjectModelRepository
{
    private $persistence;

    public function __construct(Connection $connection, string $dbPrefix, HydratorInterface $hydrator = null, PersistenceInterface $persistence = null)
    {
        parent::__construct(\Tab::class, $connection, $dbPrefix, $hydrator);

        $this->persistence = $persistence ?? new Persistence();
    }

    public function add(\Tab $tab): void
    {
        if (null === $tab->id) {
            try {
                $this->persistence->save($tab);
            } catch (\Exception $e) {
                $this->persistence->delete($tab);

                throw $e;
            }
        }

        $this->objectsById[$tab->id] = $tab;
    }

    public function update(\Tab $tab): void
    {
        if (0 >= (int) $tab->id) {
            throw new \InvalidArgumentException('Cannot update tab: identifier is invalid.');
        }

        $this->persistence->save($tab);
        $this->objectsById[$tab->id] = $tab;
    }

    public function findOneByClassName(string $name): ?\Tab
    {
        $statement = $this
            ->createLangQueryBuilder('t')
            ->andWhere('t.class_name = :className')
            ->setParameter('className', $name)
            ->execute();

        $data = $this->fetchAllAssociative($statement);
        $collection = $this->hydrateCollection($data);

        return current($collection) ?: null;
    }

    public function hasChildren(int $id): bool
    {
        if (0 >= $id) {
            return false;
        }

        $subQuery = $this
            ->createQueryBuilder('t')
            ->andWhere('t.id_parent = :parentId');

        $statement = $this->connection
            ->createQueryBuilder()
            ->select('EXISTS (' . $subQuery . ')')
            ->setParameter('parentId', $id)
            ->execute();

        return (bool) $this->fetchOne($statement);
    }
}
