<?php

namespace App\Framework\Database;

/**
 * Represents a connection wrapper in a connection pool.
 *
 * The PooledConnection class acts as a proxy for an actual database connection, managing the lifecycle
 * of the underlying connection and facilitating its return to the connection pool upon release or destruction.
 * It delegates operations to the underlying `ConnectionInterface` implementation.
 */
final class PooledConnection implements ConnectionInterface
{
    private ConnectionInterface $connection;
    private ConnectionPool $pool;
    private string $id;
    private bool $released = false;

    public function __construct(ConnectionInterface $connection, ConnectionPool $pool, string $id)
    {
        $this->connection = $connection;
        $this->pool = $pool;
        $this->id = $id;
    }

    public function execute(string $sql, array $parameters = []): int
    {
        return $this->connection->execute($sql, $parameters);
    }

    public function query(string $sql, array $parameters = []): ResultInterface
    {
        return $this->connection->query($sql, $parameters);
    }

    public function queryOne(string $sql, array $parameters = []): ?array
    {
        return $this->connection->queryOne($sql, $parameters);
    }

    public function queryColumn(string $sql, array $parameters = []): array
    {
        return $this->connection->queryColumn($sql, $parameters);
    }

    public function queryScalar(string $sql, array $parameters = []): mixed
    {
        return $this->connection->queryScalar($sql, $parameters);
    }

    public function beginTransaction(): void
    {
        $this->connection->beginTransaction();
    }

    public function commit(): void
    {
        $this->connection->commit();
    }

    public function rollback(): void
    {
        $this->connection->rollback();
    }

    public function inTransaction(): bool
    {
        return $this->connection->inTransaction();
    }

    public function lastInsertId(): string
    {
        return $this->connection->lastInsertId();
    }

    public function getPdo(): \PDO
    {
        return $this->connection->getPdo();
    }

    public function release(): void
    {
        if (!$this->released) {
            $this->pool->releaseConnection($this->id);
            $this->released = true;
        }
    }

    public function __destruct()
    {
        $this->release();
    }
}
