<?php

declare(strict_types=1);

namespace App\Framework\Database;

use App\Framework\Database\Exception\DatabaseException;

final class ConnectionPool
{
    private array $config;
    private array $connections = [];
    private array $inUse = [];
    private int $maxConnections;
    private int $minConnections;
    private int $currentConnections = 0;

    public function __construct(array $config, int $maxConnections = 10, int $minConnections = 2)
    {
        $this->config = $config;
        $this->maxConnections = $maxConnections;
        $this->minConnections = $minConnections;

        $this->initializeMinConnections();
    }

    public function getConnection(): PooledConnection
    {
        foreach ($this->connections as $id => $connection) {
            if (!isset($this->inUse[$id])) {
                $this->inUse[$id] = true;
                return new PooledConnection($connection, $this, $id);
            }
        }

        if ($this->currentConnections < $this->maxConnections) {
            $connection = DatabaseFactory::createConnection($this->config);
            $id = uniqid('conn_');
            $this->connections[$id] = $connection;
            $this->inUse[$id] = true;
            $this->currentConnections++;

            return new PooledConnection($connection, $this, $id);
        }

        throw new DatabaseException('Maximum number of connections reached');
    }

    public function releaseConnection(string $id): void
    {
        unset($this->inUse[$id]);
    }

    public function closeConnection(string $id): void
    {
        unset($this->connections[$id], $this->inUse[$id]);
        $this->currentConnections--;
    }

    public function getStats(): array
    {
        return [
            'total_connections' => $this->currentConnections,
            'active_connections' => count($this->inUse),
            'free_connections' => $this->currentConnections - count($this->inUse),
            'max_connections' => $this->maxConnections,
        ];
    }

    private function initializeMinConnections(): void
    {
        for ($i = 0; $i < $this->minConnections; $i++) {
            $connection = DatabaseFactory::createConnection($this->config);
            $id = uniqid('conn_');
            $this->connections[$id] = $connection;
            $this->currentConnections++;
        }
    }

    public function __destruct()
    {
        $this->connections = [];
        $this->inUse = [];
        $this->currentConnections = 0;
    }
}
