#include "connection_pool.h"
#include <iostream>
#include "connection_guard.h"

ConnectionPool::ConnectionPool(const std::string &host, const std::string &port,
                               const std::string &name, const std::string &user,
                               const std::string &password, int pool_size)
    : host(host), port(port), name(name), user(user), password(password) {
    createPool(pool_size);
}

void ConnectionPool::createPool(int pool_size) {
    std::string conninfo = "host=" + host + " port=" + port + " dbname=" + name +
                           " user=" + user + " password=" + password;

    for (int i = 0; i < pool_size; ++i) {
        auto conn = std::make_shared<Database>(conninfo);
        pool.push(conn);
    }
}

std::shared_ptr<Database> ConnectionPool::getConnection() {
    std::unique_lock<std::mutex> lock(pool_mutex);
    pool_cv.wait(lock, [this]() { return !pool.empty(); });
    auto conn = pool.front();
    pool.pop();
    if (!conn->isValid()) {
        std::cerr << "[ConnectionPool] Ungültige Verbindung. Erstelle neu.\n";
        std::string conninfo = "host=" + host +
                               " port=" + port +
                               " dbname=" + name +
                               " user=" + user +
                               " password=" + password;
        conn = std::make_shared<Database>(conninfo);
        if (!conn->isValid()) {
            std::cerr << "[ConnectionPool] Erneut fehlgeschlagen.\n";
            return nullptr;
        }
    }
    return conn;
}

void ConnectionPool::releaseConnection(std::shared_ptr<Database> conn) {
    {
        std::lock_guard<std::mutex> lock(pool_mutex);
        pool.push(conn);
    }
    pool_cv.notify_one();
}
