#!/usr/bin/env python3
"""
Oracle database connection pool manager using oracledb.
Manages connections with pooling and health checks.

oracledb is the modern, simpler replacement for cx_Oracle.
No Oracle Instant Client required - uses Thick or Thin mode.
"""

import oracledb
from logging_config import get_logger
from config import get_config

logger = get_logger(__name__)


class OracleConnector:
    """Manages Oracle database connections with pooling."""

    def __init__(self):
        """Initialize connection pool."""
        self.pool = None
        self.config = get_config()

    def initialize_pool(self):
        """Create connection pool."""
        try:
            # Build connection string for oracledb
            # Format: user/password@host:port/service_name
            connection_string = (
                f"{self.config.db_user}/{self.config.db_password}@"
                f"{self.config.db_host}:{self.config.db_port}/{self.config.db_service_name}"
            )

            # Create connection pool using oracledb API
            # Note: oracledb uses 'min' and 'max' for pool sizing
            self.pool = oracledb.create_pool(
                dsn=connection_string,
                min=self.config.db_pool_min,
                max=self.config.db_pool_max,
                increment=1,
            )

            logger.debug(f"Oracle connection pool initialized: min={self.config.db_pool_min}, max={self.config.db_pool_max}")
            return True
        except oracledb.DatabaseError as e:
            logger.error(f"Failed to initialize connection pool: {e}", exc_info=True)
            return False
        except Exception as e:
            logger.error(f"Unexpected error initializing pool: {e}", exc_info=True)
            return False

    def get_connection(self):
        """Get connection from pool."""
        if not self.pool:
            self.initialize_pool()

        try:
            conn = self.pool.acquire()
            logger.debug("Connection acquired from pool")
            return conn
        except oracledb.DatabaseError as e:
            logger.error(f"Failed to acquire connection: {e}", exc_info=True)
            raise
        except Exception as e:
            logger.error(f"Unexpected error acquiring connection: {e}", exc_info=True)
            raise

    def close_pool(self):
        """Close connection pool."""
        if self.pool:
            try:
                self.pool.close()
                logger.info("Connection pool closed")
            except Exception as e:
                logger.error(f"Error closing pool: {e}")

    def test_connection(self):
        """Test database connectivity."""
        try:
            conn = self.get_connection()
            cursor = conn.cursor()
            cursor.execute("SELECT 1 FROM dual")
            result = cursor.fetchone()
            cursor.close()
            conn.close()
            logger.debug("Database connection test successful")
            return True
        except Exception as e:
            logger.error(f"Database connection test failed: {e}")
            return False

    def __enter__(self):
        """Context manager entry."""
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        """Context manager exit."""
        self.close_pool()


# Global connector instance
_connector = None


def get_connector():
    """Get or create global connector instance."""
    global _connector
    if _connector is None:
        _connector = OracleConnector()
    return _connector
