/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#ifndef IOTDB_SESSIONPOOL_H
#define IOTDB_SESSIONPOOL_H

#include <chrono>
#include <condition_variable>
#include <cstdint>
#include <deque>
#include <memory>
#include <mutex>
#include <string>
#include <utility>
#include <vector>

#include "Session.h"

/*
 * A thread-safe pool of opened Session objects.
 *
 * A Session is NOT safe to use from multiple threads concurrently. SessionPool
 * solves this by lending each Session to exactly one borrower at a time and
 * reclaiming it afterwards, so many application threads can share a bounded set
 * of physical connections without external locking.
 *
 * Two usage styles are supported:
 *
 *   1. RAII lease (recommended for arbitrary calls):
 *        {
 *          PooledSession s = pool.getSession();   // blocks up to the timeout
 *          s->insertTablet(tablet);               // call any Session method
 *        }                                        // automatically returned here
 *
 *   2. Convenience wrappers / generic execute() (recommended for hot paths):
 *        pool.insertTablet(tablet);
 *        pool.execute([&](Session& s) { s.insertRecord(...); });
 *
 * Both styles evict a Session from the pool (instead of recycling it) when the
 * operation throws IoTDBConnectionException, so a dead connection is never
 * handed to the next borrower; a fresh one is created lazily on demand.
 *
 * Lifetime: a PooledSession returns its Session to the owning SessionPool when
 * destroyed, so every PooledSession must not outlive the pool it came from.
 */
class SessionPool;

class PooledSession {
public:
  PooledSession() noexcept : pool_(nullptr), session_(nullptr), broken_(false) {}

  PooledSession(SessionPool* pool, std::shared_ptr<Session> session)
      : pool_(pool), session_(std::move(session)), broken_(false) {}

  // Non-copyable: a leased Session is owned by exactly one borrower.
  PooledSession(const PooledSession&) = delete;
  PooledSession& operator=(const PooledSession&) = delete;

  PooledSession(PooledSession&& other) noexcept
      : pool_(other.pool_), session_(std::move(other.session_)), broken_(other.broken_) {
    other.pool_ = nullptr;
    other.session_ = nullptr;
    other.broken_ = false;
  }

  PooledSession& operator=(PooledSession&& other) noexcept {
    if (this != &other) {
      reset();
      pool_ = other.pool_;
      session_ = std::move(other.session_);
      broken_ = other.broken_;
      other.pool_ = nullptr;
      other.session_ = nullptr;
      other.broken_ = false;
    }
    return *this;
  }

  ~PooledSession() {
    reset();
  }

  Session* operator->() const {
    return session_.get();
  }

  Session& operator*() const {
    return *session_;
  }

  explicit operator bool() const {
    return static_cast<bool>(session_);
  }

  // Mark the underlying connection as unusable so it is discarded (not recycled)
  // when this lease is returned. Call this if you caught a connection error.
  void markBroken() {
    broken_ = true;
  }

  // Eagerly return the Session to the pool before scope exit.
  void release() {
    reset();
  }

private:
  void reset();

  SessionPool* pool_;
  std::shared_ptr<Session> session_;
  bool broken_;
};

/*
 * Couples a query result set with the pooled Session that produced it.
 *
 * A SessionDataSet lazily fetches further result blocks over its Session's
 * connection, so that Session must stay exclusively leased until iteration is
 * finished. This wrapper holds the lease for exactly that long and returns the
 * Session to the pool when destroyed.
 */
class PooledSessionDataSet {
public:
  PooledSessionDataSet(PooledSession session, std::unique_ptr<SessionDataSet> dataSet)
      : session_(std::move(session)), dataSet_(std::move(dataSet)) {}

  PooledSessionDataSet(const PooledSessionDataSet&) = delete;
  PooledSessionDataSet& operator=(const PooledSessionDataSet&) = delete;
  PooledSessionDataSet(PooledSessionDataSet&&) noexcept = default;
  PooledSessionDataSet& operator=(PooledSessionDataSet&&) noexcept = default;

  SessionDataSet* operator->() const {
    return dataSet_.get();
  }
  SessionDataSet& operator*() const {
    return *dataSet_;
  }

private:
  PooledSession session_;
  std::unique_ptr<SessionDataSet> dataSet_;
};

class SessionPool {
public:
  static constexpr size_t DEFAULT_MAX_SIZE = 5;
  static constexpr int64_t DEFAULT_WAIT_TIMEOUT_MS = 60 * 1000;

  // Single-host constructor.
  SessionPool(std::string host, int rpcPort, std::string username, std::string password,
              size_t maxSize = DEFAULT_MAX_SIZE);

  // Multi-node constructor.
  SessionPool(std::vector<std::string> nodeUrls, std::string username, std::string password,
              size_t maxSize = DEFAULT_MAX_SIZE);

  ~SessionPool();

  // Non-copyable, non-movable: the pool owns mutex/condition state.
  SessionPool(const SessionPool&) = delete;
  SessionPool& operator=(const SessionPool&) = delete;

  // ---- configuration (apply before the first getSession()) ----
  SessionPool& setFetchSize(int fetchSize);
  SessionPool& setZoneId(std::string zoneId);
  SessionPool& setSqlDialect(std::string sqlDialect);
  SessionPool& setDatabase(std::string database);
  SessionPool& setEnableRedirection(bool enable);
  SessionPool& setEnableAutoFetch(bool enable);
  SessionPool& setEnableRPCCompression(bool enable);
  SessionPool& setConnectTimeoutMs(int connectTimeoutMs);
  SessionPool& setWaitToGetSessionTimeoutMs(int64_t timeoutMs);
  SessionPool& setUseSSL(bool useSSL);
  SessionPool& setTrustCertFilePath(std::string path);
  SessionPool& setClientCertificateFilePath(std::string path);
  SessionPool& setClientPrivateKeyFilePath(std::string path);

  // Borrow a Session. Blocks until one is free or a new one can be created,
  // up to timeoutMs (<= 0 means use the pool default). Throws IoTDBException on
  // timeout or when the pool is closed.
  PooledSession getSession();
  PooledSession getSession(int64_t timeoutMs);

  // Generic helper: borrow a Session, run func(Session&), return/evict it, and
  // forward the result. Evicts the Session on IoTDBConnectionException.
  template <typename Func> auto execute(Func&& func) -> decltype(func(std::declval<Session&>()));

  // ---- convenience wrappers for common operations (with eviction on failure) ----
  void insertTablet(Tablet& tablet, bool sorted = false);
  void insertAlignedTablet(Tablet& tablet, bool sorted = false);
  void insertTablets(std::unordered_map<std::string, Tablet*>& tablets, bool sorted = false);
  void insertRecord(const std::string& deviceId, int64_t time,
                    const std::vector<std::string>& measurements,
                    const std::vector<std::string>& values);
  void insertRecords(const std::vector<std::string>& deviceIds, const std::vector<int64_t>& times,
                     const std::vector<std::vector<std::string>>& measurementsList,
                     const std::vector<std::vector<std::string>>& valuesList);
  void executeNonQueryStatement(const std::string& sql);
  // The returned wrapper keeps the underlying Session leased until it is
  // destroyed, so it is safe to iterate the result set across multiple fetches.
  PooledSessionDataSet executeQueryStatement(const std::string& sql);
  PooledSessionDataSet executeQueryStatement(const std::string& sql, int64_t timeoutInMs);

  // Close the pool: idle Sessions are closed immediately, in-use Sessions are
  // closed when they are returned. Idempotent.
  void close();

  // ---- observability ----
  size_t getMaxSize() const {
    return maxSize_;
  }
  // Number of Sessions currently borrowed.
  size_t activeCount();

private:
  friend class PooledSession;

  std::shared_ptr<Session> constructNewSession();
  std::shared_ptr<Session> acquire(int64_t timeoutMs);
  void putBack(const std::shared_ptr<Session>& session, bool broken);

  // connection parameters
  std::string host_;
  int rpcPort_;
  std::vector<std::string> nodeUrls_;
  std::string username_;
  std::string password_;
  std::string zoneId_;
  int fetchSize_ = AbstractSessionBuilder::DEFAULT_FETCH_SIZE;
  std::string sqlDialect_ = AbstractSessionBuilder::DEFAULT_SQL_DIALECT;
  std::string database_;
  bool enableRedirection_ = AbstractSessionBuilder::DEFAULT_ENABLE_REDIRECTIONS;
  bool enableAutoFetch_ = AbstractSessionBuilder::DEFAULT_ENABLE_AUTO_FETCH;
  bool enableRPCCompression_ = AbstractSessionBuilder::DEFAULT_ENABLE_RPC_COMPRESSION;
  int connectTimeoutMs_ = AbstractSessionBuilder::DEFAULT_CONNECT_TIMEOUT_MS;
  SslConfig sslConfig_;

  // pool sizing / waiting policy
  size_t maxSize_;
  int64_t waitTimeoutMs_ = DEFAULT_WAIT_TIMEOUT_MS;

  // pool state, guarded by mutex_
  std::mutex mutex_;
  std::condition_variable cv_;
  std::deque<std::shared_ptr<Session>> idleQueue_;
  size_t size_ = 0; // total live Sessions (idle + borrowed)
  bool closed_ = false;
};

template <typename Func>
auto SessionPool::execute(Func&& func) -> decltype(func(std::declval<Session&>())) {
  PooledSession lease = getSession();
  try {
    return func(*lease);
  } catch (const IoTDBConnectionException&) {
    lease.markBroken();
    throw;
  }
}

/*
 * Fluent builder for SessionPool, mirroring SessionBuilder / TableSessionBuilder.
 *
 *   auto pool = SessionPoolBuilder()
 *                   .host("127.0.0.1")->rpcPort(6667)
 *                   ->username("root")->password("root")
 *                   ->maxSize(10)->build();
 */
class SessionPoolBuilder : public AbstractSessionBuilder {
public:
  SessionPoolBuilder* host(const std::string& v) {
    AbstractSessionBuilder::host = v;
    return this;
  }
  SessionPoolBuilder* rpcPort(int v) {
    AbstractSessionBuilder::rpcPort = v;
    return this;
  }
  SessionPoolBuilder* nodeUrls(const std::vector<std::string>& v) {
    AbstractSessionBuilder::nodeUrls = v;
    return this;
  }
  SessionPoolBuilder* username(const std::string& v) {
    AbstractSessionBuilder::username = v;
    return this;
  }
  SessionPoolBuilder* password(const std::string& v) {
    AbstractSessionBuilder::password = v;
    return this;
  }
  SessionPoolBuilder* zoneId(const std::string& v) {
    AbstractSessionBuilder::zoneId = v;
    return this;
  }
  SessionPoolBuilder* fetchSize(int v) {
    AbstractSessionBuilder::fetchSize = v;
    return this;
  }
  SessionPoolBuilder* database(const std::string& v) {
    AbstractSessionBuilder::database = v;
    return this;
  }
  SessionPoolBuilder* enableAutoFetch(bool v) {
    AbstractSessionBuilder::enableAutoFetch = v;
    return this;
  }
  SessionPoolBuilder* enableRedirections(bool v) {
    AbstractSessionBuilder::enableRedirections = v;
    return this;
  }
  SessionPoolBuilder* enableRPCCompression(bool v) {
    AbstractSessionBuilder::enableRPCCompression = v;
    return this;
  }
  SessionPoolBuilder* connectTimeoutMs(int v) {
    AbstractSessionBuilder::connectTimeoutMs = v;
    return this;
  }
  SessionPoolBuilder* useSSL(bool v) {
    AbstractSessionBuilder::useSSL = v;
    AbstractSessionBuilder::sslConfig.useSsl = v;
    return this;
  }
  SessionPoolBuilder* trustCertFilePath(const std::string& v) {
    AbstractSessionBuilder::trustCertFilePath = v;
    AbstractSessionBuilder::sslConfig.trustCertFilePath = v;
    return this;
  }
  SessionPoolBuilder* clientCertificateFilePath(const std::string& v) {
    AbstractSessionBuilder::sslConfig.clientCertificateFilePath = v;
    return this;
  }
  SessionPoolBuilder* clientPrivateKeyFilePath(const std::string& v) {
    AbstractSessionBuilder::sslConfig.clientPrivateKeyFilePath = v;
    return this;
  }
  SessionPoolBuilder* maxSize(size_t v) {
    maxSize_ = v;
    return this;
  }
  SessionPoolBuilder* waitToGetSessionTimeoutMs(int64_t v) {
    waitTimeoutMs_ = v;
    return this;
  }
  SessionPoolBuilder* sqlDialect(const std::string& v) {
    AbstractSessionBuilder::sqlDialect = v;
    return this;
  }

  std::shared_ptr<SessionPool> build() {
    if (!AbstractSessionBuilder::nodeUrls.empty() &&
        (AbstractSessionBuilder::host != DEFAULT_HOST ||
         AbstractSessionBuilder::rpcPort != DEFAULT_RPC_PORT)) {
      throw IoTDBException(
          "SessionPool builder does not support setting node urls and host/rpcPort at the same "
          "time.");
    }
    std::shared_ptr<SessionPool> pool;
    if (!AbstractSessionBuilder::nodeUrls.empty()) {
      pool = std::make_shared<SessionPool>(AbstractSessionBuilder::nodeUrls,
                                           AbstractSessionBuilder::username,
                                           AbstractSessionBuilder::password, maxSize_);
    } else {
      pool = std::make_shared<SessionPool>(
          AbstractSessionBuilder::host, AbstractSessionBuilder::rpcPort,
          AbstractSessionBuilder::username, AbstractSessionBuilder::password, maxSize_);
    }
    pool->setFetchSize(AbstractSessionBuilder::fetchSize)
        .setZoneId(AbstractSessionBuilder::zoneId)
        .setSqlDialect(AbstractSessionBuilder::sqlDialect)
        .setDatabase(AbstractSessionBuilder::database)
        .setEnableRedirection(AbstractSessionBuilder::enableRedirections)
        .setEnableAutoFetch(AbstractSessionBuilder::enableAutoFetch)
        .setEnableRPCCompression(AbstractSessionBuilder::enableRPCCompression)
        .setConnectTimeoutMs(AbstractSessionBuilder::connectTimeoutMs)
        .setWaitToGetSessionTimeoutMs(waitTimeoutMs_)
        .setUseSSL(AbstractSessionBuilder::getSslConfig().useSsl)
        .setTrustCertFilePath(AbstractSessionBuilder::getSslConfig().trustCertFilePath)
        .setClientCertificateFilePath(AbstractSessionBuilder::sslConfig.clientCertificateFilePath)
        .setClientPrivateKeyFilePath(AbstractSessionBuilder::sslConfig.clientPrivateKeyFilePath);
    return pool;
  }

private:
  size_t maxSize_ = SessionPool::DEFAULT_MAX_SIZE;
  int64_t waitTimeoutMs_ = SessionPool::DEFAULT_WAIT_TIMEOUT_MS;
};

#endif // IOTDB_SESSIONPOOL_H
