"""Enhanced authentication with proper security practices."""

import hashlib
import hmac
import logging
from typing import Optional

from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials

from .config import MonitorConfig
from .exceptions import AuthenticationError

logger = logging.getLogger(__name__)

security = HTTPBasic()


class AuthService:
    """Authentication service with enhanced security."""

    def __init__(self, config: MonitorConfig):
        self.config = config
        self._username_hash: Optional[bytes] = None
        self._password_hash: Optional[bytes] = None

        if config.dashboard_username and config.dashboard_password:
            self._username_hash = self._hash_credential(config.dashboard_username)
            self._password_hash = self._hash_credential(config.dashboard_password)

    def _hash_credential(self, credential: str) -> bytes:
        """Hash credential using SHA-256."""
        return hashlib.sha256(credential.encode()).digest()

    def _secure_compare(self, provided: str, stored_hash: bytes) -> bool:
        """Securely compare provided credential with stored hash."""
        provided_hash = self._hash_credential(provided)
        return hmac.compare_digest(provided_hash, stored_hash)

    def authenticate(self, credentials: HTTPBasicCredentials) -> str:
        """Authenticate user credentials."""
        if not self._username_hash or not self._password_hash:
            raise AuthenticationError("Authentication not configured")

        try:
            # Use constant-time comparison to prevent timing attacks
            username_valid = self._secure_compare(credentials.username, self._username_hash)
            password_valid = self._secure_compare(credentials.password, self._password_hash)

            if not (username_valid and password_valid):
                logger.warning(f"Failed authentication attempt for user: {credentials.username}")
                raise HTTPException(
                    status_code=status.HTTP_401_UNAUTHORIZED,
                    detail="Invalid credentials",
                    headers={"WWW-Authenticate": "Basic"},
                )

            logger.info(f"Successful authentication for user: {credentials.username}")
            return credentials.username

        except HTTPException:
            raise
        except Exception as e:
            logger.error(f"Authentication error: {e}")
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail="Authentication service error"
            )

    def is_enabled(self) -> bool:
        """Check if authentication is enabled."""
        return self._username_hash is not None and self._password_hash is not None


def create_auth_dependency(config: MonitorConfig):
    """Create authentication dependency based on configuration."""
    auth_service = AuthService(config)

    if not auth_service.is_enabled():
        # No authentication required
        def no_auth() -> Optional[str]:
            return None
        return no_auth

    # Authentication required
    def authenticate(credentials: HTTPBasicCredentials = Depends(security)) -> str:
        return auth_service.authenticate(credentials)

    return authenticate


# Legacy compatibility functions
def create_auth_dependency_legacy(username: str, password: str):
    """Legacy function for backward compatibility."""
    config = MonitorConfig(
        dashboard_username=username,
        dashboard_password=password
    )
    return create_auth_dependency(config)


def no_auth() -> Optional[str]:
    """No authentication dependency."""
    return None
