<?php

declare(strict_types=1);

namespace Atk4\Data\Schema;

use Atk4\Data\Persistence;
use Doctrine\DBAL\Logging\SQLLogger;
use Doctrine\DBAL\Platforms\MySQLPlatform;

/**
 * SQL persistence with lazy connect and SQL logger.
 *
 * @internal
 */
class TestSqlPersistence extends Persistence\Sql
{
    public function __construct() {} // @phpstan-ignore constructor.missingParentCall

    #[\Override]
    public function getConnection(): Persistence\Sql\Connection
    {
        \Closure::bind(function () {
            if (($this->_connection ?? null) === null) {
                $this->_connection = Persistence::connect($_ENV['DB_DSN'], $_ENV['DB_USER'], $_ENV['DB_PASSWORD'])->_connection; // @phpstan-ignore property.notFound

                if ($this->getDatabasePlatform() instanceof MySQLPlatform) {
                    $this->getConnection()->expr(
                        'SET SESSION auto_increment_increment = 1, SESSION auto_increment_offset = 1'
                    )->executeStatement();
                }

                $this->getConnection()->getConnection()->getConfiguration()->setSQLLogger( // @phpstan-ignore method.deprecated
                    // @phpstan-ignore class.implementsDeprecatedInterface (TODO PHP CS Fixer should allow comment on the same line)
                    new class implements SQLLogger {
                        #[\Override]
                        public function startQuery($sql, ?array $params = null, ?array $types = null): void
                        {
                            // log transaction savepoint operations only once
                            // https://github.com/doctrine/dbal/blob/3.6.7/src/Connection.php#L1365
                            if (preg_match('~^(?:SAVEPOINT|RELEASE SAVEPOINT|ROLLBACK TO SAVEPOINT|SAVE TRANSACTION|ROLLBACK TRANSACTION) DOCTRINE2_SAVEPOINT_\d+;?$~', $sql)) {
                                return;
                            }

                            // fix https://github.com/doctrine/dbal/issues/5525
                            if ($params !== null && $params !== [] && array_is_list($params)) {
                                $params = array_combine(range(1, count($params)), $params);
                            }

                            $test = TestCase::getTestFromBacktrace();
                            \Closure::bind(static fn () => $test->logQuery($sql, $params ?? [], $types ?? []), null, TestCase::class)(); // @phpstan-ignore argument.type
                        }

                        #[\Override]
                        public function stopQuery(): void {}
                    }
                );
            }
        }, $this, Persistence\Sql::class)();

        return parent::getConnection();
    }
}
