"""
Configuration Management for CXR Kernel Service

Handles database and Qdrant connections via environment variables.
"""

import os
from typing import Optional
import structlog

logger = structlog.get_logger(__name__)


class KernelConfig:
    """Configuration for CXR Kernel Service"""
    
    # Database configuration
    DB_DRIVER: str = os.getenv("CXR_DB_DRIVER", "ODBC Driver 17 for SQL Server")
    DB_SERVER: Optional[str] = os.getenv("CXR_DB_SERVER")
    DB_PORT: int = int(os.getenv("CXR_DB_PORT", "1433"))
    DB_NAME: Optional[str] = os.getenv("CXR_DB_NAME")
    DB_USER: Optional[str] = os.getenv("CXR_DB_USER")
    DB_PASSWORD: Optional[str] = os.getenv("CXR_DB_PASSWORD")
    DB_TRUSTED_CONNECTION: bool = os.getenv("CXR_DB_TRUSTED_CONNECTION", "false").lower() == "true"
    
    # Qdrant configuration
    QDRANT_HOST: Optional[str] = os.getenv("CXR_QDRANT_HOST")
    QDRANT_PORT: int = int(os.getenv("CXR_QDRANT_PORT", "6333"))
    QDRANT_API_KEY: Optional[str] = os.getenv("CXR_QDRANT_API_KEY")
    QDRANT_HTTPS: bool = os.getenv("CXR_QDRANT_HTTPS", "false").lower() == "true"
    
    # Alternative: Full connection strings
    DB_CONNECTION_STRING: Optional[str] = os.getenv("CXR_DB_CONNECTION_STRING")
    
    @classmethod
    def get_db_connection_string(cls) -> Optional[str]:
        """
        Build database connection string from environment variables.
        
        Returns:
            Connection string for pyodbc, or None if not configured
        """
        # If full connection string provided, use it
        if cls.DB_CONNECTION_STRING:
            return cls.DB_CONNECTION_STRING
        
        # Otherwise, build from components
        if not cls.DB_SERVER or not cls.DB_NAME:
            return None
        
        if cls.DB_TRUSTED_CONNECTION:
            conn_str = (
                f"DRIVER={{{cls.DB_DRIVER}}};"
                f"SERVER={cls.DB_SERVER},{cls.DB_PORT};"
                f"DATABASE={cls.DB_NAME};"
                f"Trusted_Connection=yes;"
            )
        else:
            if not cls.DB_USER or not cls.DB_PASSWORD:
                return None
            conn_str = (
                f"DRIVER={{{cls.DB_DRIVER}}};"
                f"SERVER={cls.DB_SERVER},{cls.DB_PORT};"
                f"DATABASE={cls.DB_NAME};"
                f"UID={cls.DB_USER};"
                f"PWD={cls.DB_PASSWORD};"
            )
        
        return conn_str
    
    @classmethod
    def get_qdrant_config(cls) -> dict:
        """
        Get Qdrant client configuration.
        
        Returns:
            Dictionary with Qdrant client configuration
        """
        config = {}
        
        if cls.QDRANT_HOST:
            config["host"] = cls.QDRANT_HOST
            config["port"] = cls.QDRANT_PORT
        
        if cls.QDRANT_API_KEY:
            config["api_key"] = cls.QDRANT_API_KEY
        
        if cls.QDRANT_HTTPS:
            config["https"] = True
        
        return config
    
    @classmethod
    def is_configured(cls) -> bool:
        """Check if minimum configuration is present"""
        db_configured = cls.DB_CONNECTION_STRING is not None or (
            cls.DB_SERVER is not None and cls.DB_NAME is not None
        )
        return db_configured
    
    @classmethod
    def validate(cls) -> list[str]:
        """
        Validate configuration and return list of missing required settings.
        
        Returns:
            List of missing configuration keys
        """
        missing = []
        
        # Database validation
        if not cls.DB_CONNECTION_STRING:
            if not cls.DB_SERVER:
                missing.append("CXR_DB_SERVER")
            if not cls.DB_NAME:
                missing.append("CXR_DB_NAME")
            if not cls.DB_TRUSTED_CONNECTION:
                if not cls.DB_USER:
                    missing.append("CXR_DB_USER")
                if not cls.DB_PASSWORD:
                    missing.append("CXR_DB_PASSWORD")
        
        return missing


def create_db_connection():
    """
    Create a database connection using configuration.
    
    Returns:
        pyodbc connection object
        
    Raises:
        NotImplementedError: If database is not configured
        ImportError: If pyodbc is not installed
    """
    try:
        import pyodbc
    except ImportError:
        raise ImportError("pyodbc is required for database connections. Install with: pip install pyodbc")
    
    conn_str = KernelConfig.get_db_connection_string()
    if not conn_str:
        raise NotImplementedError(
            "Database connection must be configured. Set environment variables:\n"
            "  - CXR_DB_CONNECTION_STRING (full connection string), OR\n"
            "  - CXR_DB_SERVER, CXR_DB_NAME, CXR_DB_USER, CXR_DB_PASSWORD"
        )
    
    try:
        conn = pyodbc.connect(conn_str)
        logger.info("kernel.db_connected", server=KernelConfig.DB_SERVER, database=KernelConfig.DB_NAME)
        return conn
    except Exception as e:
        logger.error("kernel.db_connection_failed", error=str(e))
        raise


def create_qdrant_client():
    """
    Create a Qdrant client using configuration.
    
    Returns:
        QdrantClient instance
        
    Raises:
        NotImplementedError: If Qdrant is not configured
        ImportError: If qdrant-client is not installed
    """
    try:
        from qdrant_client import QdrantClient
    except ImportError:
        raise ImportError(
            "qdrant-client is required for vector search. Install with: pip install qdrant-client"
        )
    
    config = KernelConfig.get_qdrant_config()
    if not config or "host" not in config:
        raise NotImplementedError(
            "Qdrant client must be configured. Set environment variables:\n"
            "  - CXR_QDRANT_HOST (required)\n"
            "  - CXR_QDRANT_PORT (optional, default: 6333)\n"
            "  - CXR_QDRANT_API_KEY (optional)\n"
            "  - CXR_QDRANT_HTTPS (optional, default: false)"
        )
    
    try:
        client = QdrantClient(**config)
        logger.info("kernel.qdrant_connected", host=config["host"], port=config.get("port", 6333))
        return client
    except Exception as e:
        logger.error("kernel.qdrant_connection_failed", error=str(e))
        raise

