#!/usr/bin/env python3
"""
Secure Credential Manager (UVS-H05)
===================================
Securely retrieves API keys from keyring with fallback to environment variables.

Security Features:
- Primary: System keyring (Windows Credential Manager, macOS Keychain, Linux Secret Service)
- Fallback: Environment variables (not .env file)
- No credential printing in logs
- Rotation support hook

VERIFICATION_STAMP
Story: UVS-H05
Verified By: Claude Opus 4.5
Verified At: 2026-02-03
"""

import os
import logging
from typing import Optional
from functools import lru_cache

logger = logging.getLogger(__name__)

# Service name for keyring storage
KEYRING_SERVICE = "genesis-system"

# Try to import keyring
try:
    import keyring
    KEYRING_AVAILABLE = True
except ImportError:
    KEYRING_AVAILABLE = False
    logger.info("keyring not available, using environment variables only")


def _mask_credential(value: str, visible_chars: int = 4) -> str:
    """Mask a credential for safe logging."""
    if not value:
        return "(empty)"
    if len(value) <= visible_chars * 2:
        return "*" * len(value)
    return f"{value[:visible_chars]}...{value[-visible_chars:]}"


def get_credential(key_name: str, fallback_env_var: Optional[str] = None) -> Optional[str]:
    """
    Retrieve a credential securely.

    Priority:
    1. System keyring (if available)
    2. Environment variable
    3. None (no .env file reading)

    Args:
        key_name: Name of the credential in keyring
        fallback_env_var: Environment variable name for fallback

    Returns:
        The credential value or None if not found
    """
    credential = None

    # 1. Try keyring first
    if KEYRING_AVAILABLE:
        try:
            credential = keyring.get_password(KEYRING_SERVICE, key_name)
            if credential:
                logger.debug(f"Credential '{key_name}' loaded from keyring")
                return credential
        except Exception as e:
            logger.warning(f"Keyring access failed for '{key_name}': {type(e).__name__}")

    # 2. Fallback to environment variable
    env_var = fallback_env_var or key_name
    credential = os.environ.get(env_var)

    if credential:
        # Log that we're using env var (but NOT the value)
        logger.debug(f"Credential '{key_name}' loaded from environment variable")
        return credential

    logger.warning(f"Credential '{key_name}' not found in keyring or environment")
    return None


def set_credential(key_name: str, value: str) -> bool:
    """
    Store a credential in the system keyring.

    Args:
        key_name: Name of the credential
        value: The credential value

    Returns:
        True if stored successfully, False otherwise
    """
    if not KEYRING_AVAILABLE:
        logger.warning("Cannot store credential: keyring not available")
        return False

    try:
        keyring.set_password(KEYRING_SERVICE, key_name, value)
        logger.info(f"Credential '{key_name}' stored in keyring")
        return True
    except Exception as e:
        logger.error(f"Failed to store credential '{key_name}': {type(e).__name__}")
        return False


def delete_credential(key_name: str) -> bool:
    """
    Delete a credential from the system keyring.

    Args:
        key_name: Name of the credential to delete

    Returns:
        True if deleted successfully, False otherwise
    """
    if not KEYRING_AVAILABLE:
        return False

    try:
        keyring.delete_password(KEYRING_SERVICE, key_name)
        logger.info(f"Credential '{key_name}' deleted from keyring")
        return True
    except Exception as e:
        logger.warning(f"Failed to delete credential '{key_name}': {type(e).__name__}")
        return False


def rotate_credential(key_name: str, new_value: str) -> bool:
    """
    Rotate a credential (delete old, set new).

    Args:
        key_name: Name of the credential
        new_value: The new credential value

    Returns:
        True if rotated successfully
    """
    # For keyring, we can just overwrite
    if KEYRING_AVAILABLE:
        return set_credential(key_name, new_value)

    logger.warning("Credential rotation requires keyring support")
    return False


# Pre-defined credential names for Genesis
class CredentialKeys:
    """Standard credential key names."""
    GEMINI_API_KEY = "gemini_api_key"
    GOOGLE_API_KEY = "google_api_key"
    GHL_API_KEY = "ghl_api_key"
    OPENAI_API_KEY = "openai_api_key"
    ANTHROPIC_API_KEY = "anthropic_api_key"


# Convenience functions for common credentials
def get_gemini_api_key() -> Optional[str]:
    """Get Gemini API key (checks both GEMINI_API_KEY and GOOGLE_API_KEY)."""
    key = get_credential(CredentialKeys.GEMINI_API_KEY, "GEMINI_API_KEY")
    if not key:
        key = get_credential(CredentialKeys.GOOGLE_API_KEY, "GOOGLE_API_KEY")
    return key


def get_ghl_api_key() -> Optional[str]:
    """Get GoHighLevel API key."""
    return get_credential(CredentialKeys.GHL_API_KEY, "GHL_API_KEY")


# Credential status check (for health monitoring)
def check_credential_status() -> dict:
    """
    Check status of required credentials (without exposing values).

    Returns:
        Dict with credential availability status
    """
    return {
        "keyring_available": KEYRING_AVAILABLE,
        "gemini_configured": get_gemini_api_key() is not None,
        "ghl_configured": get_ghl_api_key() is not None,
    }
