# Copyright (c) 2025 Patrick Motsch
# All rights reserved.
"""
Security service for token management operations.
Core service - not requested by features directly.
"""

import logging
from typing import Optional, Callable, Any

from modules.datamodels.datamodelSecurity import Token, TokenPurpose
from modules.auth import TokenManager

logger = logging.getLogger(__name__)


class SecurityService:
    """Security service providing token management operations."""

    def __init__(self, context: Any, get_service: Callable[[str], Any]):
        """Initialize with service center context and resolver."""
        self._context = context
        self._get_service = get_service
        self._tokenManager = TokenManager()
        from modules.interfaces.interfaceDbApp import getInterface as getAppInterface
        self._interfaceDbApp = getAppInterface(
            context.user,
            mandateId=context.mandate_id,
        )

    def getFreshToken(self, connectionId: str, secondsBeforeExpiry: int = 30 * 60) -> Optional[Token]:
        """Get a fresh token for a connection, refreshing when expiring soon."""
        try:
            token = self._interfaceDbApp.getConnectionToken(connectionId)
            if not token:
                return None
            _tp = (
                token.tokenPurpose.value
                if isinstance(token.tokenPurpose, TokenPurpose)
                else token.tokenPurpose
            )
            if _tp != TokenPurpose.DATA_CONNECTION.value:
                logger.warning(
                    f"getFreshToken: connection {connectionId} tokenPurpose is {_tp}, expected dataConnection"
                )
                return None
            return self._tokenManager.ensureFreshToken(
                token,
                secondsBeforeExpiry=secondsBeforeExpiry,
                saveCallback=lambda t: self._interfaceDbApp.saveConnectionToken(t)
            )
        except Exception as e:
            logger.error(f"getFreshToken: Error fetching or refreshing token for connection {connectionId}: {e}")
            return None

    def refreshToken(self, oldToken: Token) -> Optional[Token]:
        """Refresh an expired token using the appropriate OAuth service."""
        try:
            return self._tokenManager.refreshToken(oldToken)
        except Exception as e:
            logger.error(f"refreshToken: Error refreshing token: {e}")
            return None

    def ensureFreshToken(self, token: Token, *, secondsBeforeExpiry: int = 30 * 60,
                        saveCallback: Optional[Callable[[Token], None]] = None) -> Optional[Token]:
        """Ensure a token is fresh; refresh if expiring within threshold."""
        try:
            return self._tokenManager.ensureFreshToken(
                token,
                secondsBeforeExpiry=secondsBeforeExpiry,
                saveCallback=saveCallback
            )
        except Exception as e:
            logger.error(f"ensureFreshToken: Error ensuring fresh token: {e}")
            return None

    def refreshMicrosoftToken(self, refreshToken: str, userId: str, oldToken: Token) -> Optional[Token]:
        """Refresh Microsoft OAuth token using refresh token."""
        try:
            return self._tokenManager.refreshMicrosoftToken(refreshToken, userId, oldToken)
        except Exception as e:
            logger.error(f"refreshMicrosoftToken: Error refreshing Microsoft token: {e}")
            return None

    def refreshGoogleToken(self, refreshToken: str, userId: str, oldToken: Token) -> Optional[Token]:
        """Refresh Google OAuth token using refresh token."""
        try:
            return self._tokenManager.refreshGoogleToken(refreshToken, userId, oldToken)
        except Exception as e:
            logger.error(f"refreshGoogleToken: Error refreshing Google token: {e}")
            return None
