import os
from pymongo import MongoClient
from dotenv import load_dotenv
from urllib.parse import quote_plus

# Load environment variables
load_dotenv()


class DatabaseConnection:
    _instance = None
    _client = None
    _db = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super(DatabaseConnection, cls).__new__(cls)
            cls._instance._initialize_connection()
        return cls._instance

    def _initialize_connection(self):
        """Initialize database connection once"""
        print("=== Initializing Database Connection ===")
        
        # Get database configuration from environment
        host = os.getenv("DB_LIVE_HOST", "localhost")
        port = int(os.getenv("DB_LIVE_PORT", "27020"))
        database = os.getenv("DB_LIVE_DATABASE", "drjobs_live")
        username = os.getenv("DB_LIVE_USERNAME", "dreamztech")
        password = os.getenv("DB_LIVE_PASSWORD")
        auth_database = os.getenv("DB_LIVE_AUTH_DATABASE", "admin")
        
        print(f"Host: {host}")
        print(f"Port: {port}")
        print(f"Database: {database}")
        print(f"Username: {username}")
        print(f"Auth Database: {auth_database}")
        
        # URL encode username and password to handle special characters
        encoded_username = quote_plus(username)
        encoded_password = quote_plus(password)
        
        # Create connection string with authentication and jump server optimized settings
        connection_string = f"mongodb://{encoded_username}:{encoded_password}@{host}:{port}/{database}?authSource={auth_database}&directConnection=true"
        print(f"Connecting to MongoDB with connection string: {connection_string}")

        try:
            # Create client with jump server optimized settings
            self._client = MongoClient(
                connection_string,
                serverSelectionTimeoutMS=30000,  # Increased timeout for jump server
                connectTimeoutMS=30000,          # Increased connection timeout
                socketTimeoutMS=30000,           # Increased socket timeout
                heartbeatFrequencyMS=10000,      # Heartbeat frequency
                maxPoolSize=10,                  # Connection pool size
                retryWrites=False,               # Disable retry writes for jump server
                directConnection=True            # Direct connection for jump server
            )
            self._db = self._client[database]
            
            # Test the connection with longer timeout for jump server
            print("Testing database connection...")
            self._client.admin.command('ping')
            print("MongoDB connection successful!")
            
            # Print database info
            print(f"Connected to database: {database}")
            try:
                collections = self._db.list_collection_names()
                print(f"Available collections: {collections}")
            except Exception as e:
                print(f"Could not list collections: {str(e)}")
            
        except Exception as e:
            print(f"MongoDB connection failed: {str(e)}")
            print("This might be due to jump server connectivity issues.")
            print("Setting client and db to None...")
            self._client = None
            self._db = None

    @property
    def client(self):
        """Get MongoDB client"""
        return self._client

    @property
    def db(self):
        """Get MongoDB database"""
        return self._db

    def is_connected(self):
        """Check if database is connected"""
        return self._client is not None and self._db is not None

    def test_connection(self):
        """Test database connection"""
        try:
            if self._client:
                self._client.admin.command('ping')
                return True
        except Exception as e:
            print(f"Connection test failed: {str(e)}")
            return False
        return False


# Create global instance
db_connection = DatabaseConnection()


def get_database():
    """Get database instance"""
    return db_connection.db


def get_client():
    """Get MongoDB client instance"""
    return db_connection.client


def is_database_connected():
    """Check if database is connected"""
    return db_connection.is_connected()