"""
Genesis Secrets Loader
======================
Secure credential management for Genesis memory system.

Priority Order:
1. Environment variables (production)
2. secrets.env file (development)
3. Default to None (fail safely)

NEVER commit actual credentials to source code.

Usage:
    from secrets_loader import get_redis_config, get_qdrant_config

    redis = get_redis_config()
    qdrant = get_qdrant_config()
"""

import os
from pathlib import Path
from typing import Optional, Dict, Any
from dataclasses import dataclass
import warnings


@dataclass(frozen=True)
class RedisConfig:
    """Redis connection configuration."""
    host: str
    port: int
    password: Optional[str]
    ssl: bool = False

    @property
    def is_configured(self) -> bool:
        """Check if Redis is properly configured."""
        return bool(self.host and self.port)

    def to_dict(self) -> Dict[str, Any]:
        """Convert to dictionary for backwards compatibility."""
        return {
            "host": self.host,
            "port": self.port,
            "password": self.password,
            "ssl": self.ssl
        }


@dataclass(frozen=True)
class QdrantConfig:
    """Qdrant vector database configuration."""
    host: str
    port: int
    api_key: Optional[str]
    collection_name: str = "genesis_memories"
    use_https: bool = True

    @property
    def is_configured(self) -> bool:
        """Check if Qdrant is properly configured."""
        return bool(self.host and self.port)

    @property
    def url(self) -> str:
        """Get full URL for Qdrant connection."""
        protocol = "https" if self.use_https else "http"
        return f"{protocol}://{self.host}:{self.port}"

    def to_dict(self) -> Dict[str, Any]:
        """Convert to dictionary for backwards compatibility."""
        return {
            "host": self.host,
            "port": self.port,
            "api_key": self.api_key,
            "collection_name": self.collection_name,
            "url": self.url
        }


@dataclass(frozen=True)
class PostgresConfig:
    """PostgreSQL connection configuration."""
    host: str
    port: int
    user: str
    password: str
    dbname: str
    sslmode: str = "require"

    @property
    def is_configured(self) -> bool:
        """Check if PostgreSQL is properly configured."""
        return all([self.host, self.port, self.user, self.password, self.dbname])

    def to_dsn(self) -> str:
        """Return a DSN string for psycopg2."""
        return f"dbname='{self.dbname}' user='{self.user}' host='{self.host}' password='{self.password}' port='{self.port}' sslmode='{self.sslmode}'"


@dataclass(frozen=True)
class MCPConfig:
    """MCP (Model Context Protocol) configuration."""
    endpoint: Optional[str]
    api_key: Optional[str]

    @property
    def is_configured(self) -> bool:
        """Check if MCP is properly configured."""
        return bool(self.endpoint)


# Cache for loaded env file
_env_cache: Dict[str, str] = {}
_env_loaded: bool = False


def _load_env_file(env_path: Optional[Path] = None) -> None:
    """
    Load environment variables from secrets.env file.
    Only loads once, caches results.
    """
    global _env_cache, _env_loaded

    if _env_loaded:
        return

    # Search paths for secrets.env
    search_paths = [
        env_path,
        Path("/mnt/e/genesis-system/config/secrets.env"),
        Path("E:/genesis-system/config/secrets.env"),
        Path.home() / ".genesis" / "secrets.env",
        Path.cwd() / "secrets.env",
    ]

    for path in search_paths:
        if path and path.exists():
            try:
                with open(path, 'r') as f:
                    for line in f:
                        line = line.strip()
                        # Skip comments and empty lines
                        if not line or line.startswith('#'):
                            continue
                        # Parse KEY=value
                        if '=' in line:
                            key, _, value = line.partition('=')
                            key = key.strip()
                            value = value.strip()
                            # Remove quotes if present
                            if value.startswith('"') and value.endswith('"'):
                                value = value[1:-1]
                            elif value.startswith("'") and value.endswith("'"):
                                value = value[1:-1]
                            _env_cache[key] = value
                print(f"[OK] Secrets loaded from: {path}")
                break
            except Exception as e:
                warnings.warn(f"Failed to load secrets from {path}: {e}")

    _env_loaded = True


def _get_env(key: str, default: Optional[str] = None) -> Optional[str]:
    """
    Get environment variable with fallback to env file.
    Priority: OS env var > secrets.env file > default
    """
    # Check OS environment first (highest priority)
    value = os.environ.get(key)
    if value:
        return value

    # Load and check env file
    _load_env_file()
    value = _env_cache.get(key)
    if value:
        return value

    return default


def get_redis_config() -> RedisConfig:
    """
    Get Redis configuration from environment.

    Environment Variables:
        GENESIS_REDIS_HOST: Redis host (default: localhost)
        GENESIS_REDIS_PORT: Redis port (default: 6379)
        GENESIS_REDIS_PASSWORD: Redis password (optional)
        GENESIS_REDIS_SSL: Use SSL (default: false)

    Returns:
        RedisConfig with connection parameters
    """
    host = _get_env("GENESIS_REDIS_HOST", "localhost")
    port_str = _get_env("GENESIS_REDIS_PORT", "6379")
    password = _get_env("GENESIS_REDIS_PASSWORD")
    ssl_str = _get_env("GENESIS_REDIS_SSL", "false")

    try:
        port = int(port_str)
    except ValueError:
        port = 6379
        warnings.warn(f"Invalid GENESIS_REDIS_PORT '{port_str}', using 6379")

    ssl = ssl_str.lower() in ("true", "1", "yes")

    return RedisConfig(
        host=host,
        port=port,
        password=password,
        ssl=ssl
    )


def get_qdrant_config() -> QdrantConfig:
    """
    Get Qdrant configuration from environment.

    Environment Variables:
        GENESIS_QDRANT_HOST: Qdrant host
        GENESIS_QDRANT_PORT: Qdrant port (default: 6333)
        GENESIS_QDRANT_API_KEY: Qdrant API key (optional)
        GENESIS_QDRANT_COLLECTION: Collection name (default: genesis_memories)
        GENESIS_QDRANT_HTTPS: Use HTTPS (default: true)

    Returns:
        QdrantConfig with connection parameters
    """
    host = _get_env("GENESIS_QDRANT_HOST", "")
    port_str = _get_env("GENESIS_QDRANT_PORT", "6333")
    api_key = _get_env("GENESIS_QDRANT_API_KEY")
    collection = _get_env("GENESIS_QDRANT_COLLECTION", "genesis_memories")
    https_str = _get_env("GENESIS_QDRANT_HTTPS", "true")

    try:
        port = int(port_str)
    except ValueError:
        port = 6333
        warnings.warn(f"Invalid GENESIS_QDRANT_PORT '{port_str}', using 6333")

    use_https = https_str.lower() in ("true", "1", "yes")

    return QdrantConfig(
        host=host,
        port=port,
        api_key=api_key,
        collection_name=collection,
        use_https=use_https
    )


def get_postgres_config() -> PostgresConfig:
    """
    Get PostgreSQL configuration from environment.

    Environment Variables:
        GENESIS_PG_HOST
        GENESIS_PG_PORT
        GENESIS_PG_USER
        GENESIS_PG_PASSWORD
        GENESIS_PG_DB
        GENESIS_PG_SSLMODE (default: require)
    """
    host = _get_env("GENESIS_PG_HOST", "")
    port_str = _get_env("GENESIS_PG_PORT", "5432")
    user = _get_env("GENESIS_PG_USER", "")
    password = _get_env("GENESIS_PG_PASSWORD", "")
    dbname = _get_env("GENESIS_PG_DB", "")
    sslmode = _get_env("GENESIS_PG_SSLMODE", "require")

    try:
        port = int(port_str)
    except (ValueError, TypeError):
        port = 5432
        warnings.warn(f"Invalid GENESIS_PG_PORT '{port_str}', using 5432")

    return PostgresConfig(
        host=host,
        port=port,
        user=user,
        password=password,
        dbname=dbname,
        sslmode=sslmode,
    )


def get_mcp_config() -> MCPConfig:
    """
    Get MCP configuration from environment.

    Environment Variables:
        GENESIS_MCP_ENDPOINT: MCP server endpoint
        GENESIS_MCP_API_KEY: MCP API key (optional)

    Returns:
        MCPConfig with connection parameters
    """
    endpoint = _get_env("GENESIS_MCP_ENDPOINT")
    api_key = _get_env("GENESIS_MCP_API_KEY")

    return MCPConfig(endpoint=endpoint, api_key=api_key)


def get_anthropic_api_key() -> Optional[str]:
    """Get Anthropic API key for LLM calls."""
    return _get_env("ANTHROPIC_API_KEY")


def get_openai_api_key() -> Optional[str]:
    """Get OpenAI API key for embeddings/fallback."""
    return _get_env("OPENAI_API_KEY")

def get_gemini_api_key() -> Optional[str]:
    """Get Gemini API key."""
    return _get_env("GEMINI_API_KEY") or _get_env("GOOGLE_API_KEY")


def get_telnyx_api_key() -> Optional[str]:
    """Get Telnyx API key."""
    return _get_env("TELNYX_API_KEY")


def validate_secrets(require_all: bool = False) -> Dict[str, bool]:
    """
    Validate that required secrets are configured.

    Args:
        require_all: If True, check all secrets. If False, only core ones.

    Returns:
        Dict mapping secret name to availability status
    """
    redis = get_redis_config()
    qdrant = get_qdrant_config()
    mcp = get_mcp_config()

    status = {
        "redis_host": bool(redis.host and redis.host != "localhost"),
        "redis_password": bool(redis.password),
        "qdrant_host": bool(qdrant.host),
        "qdrant_api_key": bool(qdrant.api_key),
        "mcp_endpoint": bool(mcp.endpoint),
        "anthropic_api_key": bool(get_anthropic_api_key()),
    }

    if require_all:
        status["openai_api_key"] = bool(get_openai_api_key())
        status["mcp_api_key"] = bool(mcp.api_key)

    return status


def print_secrets_status() -> None:
    """Print current secrets configuration status (safe, no values shown)."""
    status = validate_secrets(require_all=True)

    print("\n=== Genesis Secrets Status ===")
    for key, available in status.items():
        icon = "✓" if available else "✗"
        print(f"  {icon} {key}")

    configured = sum(1 for v in status.values() if v)
    total = len(status)
    print(f"\nConfigured: {configured}/{total}")

    if configured < 4:
        print("\n[!] Some core secrets missing. Create secrets.env or set environment variables.")
        print("    See: /mnt/e/genesis-system/config/secrets.env.template")


# CLI interface
if __name__ == "__main__":
    import sys

    if len(sys.argv) > 1:
        cmd = sys.argv[1]

        if cmd == "status":
            print_secrets_status()

        elif cmd == "validate":
            status = validate_secrets()
            all_ok = all(status.values())
            if all_ok:
                print("[OK] All core secrets configured")
                sys.exit(0)
            else:
                missing = [k for k, v in status.items() if not v]
                print(f"[!] Missing secrets: {', '.join(missing)}")
                sys.exit(1)

        elif cmd == "test-redis":
            config = get_redis_config()
            print(f"Redis: {config.host}:{config.port} (password: {'set' if config.password else 'none'})")

        elif cmd == "test-qdrant":
            config = get_qdrant_config()
            print(f"Qdrant: {config.url} (key: {'set' if config.api_key else 'none'})")

        else:
            print(f"Unknown command: {cmd}")
            print("Usage: python secrets_loader.py [status|validate|test-redis|test-qdrant]")
    else:
        print_secrets_status()
