# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""MCP Server that requires OAuth Bearer token for both tool listing and calling.

This server validates the Authorization header on every request including:
- Tool listing (list_tools endpoint)
- Tool calling (call_tool endpoint)

This is used to test the toolset authentication feature in ADK.
"""

from __future__ import annotations

import logging

from fastapi import FastAPI
from fastapi import HTTPException
from fastapi import Request
from mcp.server.fastmcp import Context
from mcp.server.fastmcp import FastMCP
import uvicorn

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('google_adk.' + __name__)

# Expected OAuth token for testing
VALID_TOKEN = 'test_access_token_12345'

# Create FastMCP server
mcp = FastMCP('OAuth Protected MCP Server', host='localhost', port=3001)


def validate_auth_header(request: Request) -> bool:
  """Validate the Authorization header contains a valid Bearer token."""
  auth_header = request.headers.get('authorization', '')
  if not auth_header.startswith('Bearer '):
    logger.warning('Missing or invalid Authorization header: %s', auth_header)
    return False

  token = auth_header[7:]  # Remove 'Bearer ' prefix
  if token != VALID_TOKEN:
    logger.warning('Invalid token: %s', token)
    return False

  logger.info('Valid token received')
  return True


@mcp.tool(description='Get user profile information. Requires authentication.')
def get_user_profile(user_id: str, context: Context) -> dict:
  """Return user profile data for the given user ID."""
  logger.info('get_user_profile called for user: %s', user_id)

  if context.request_context and context.request_context.request:
    if not validate_auth_header(context.request_context.request):
      return {'error': 'Unauthorized - invalid or missing token'}

  # Mock user data
  users = {
      'user1': {'id': 'user1', 'name': 'Alice', 'email': 'alice@example.com'},
      'user2': {'id': 'user2', 'name': 'Bob', 'email': 'bob@example.com'},
  }

  if user_id in users:
    return users[user_id]
  return {'error': f'User {user_id} not found'}


@mcp.tool(description='List all available users. Requires authentication.')
def list_users(context: Context) -> dict:
  """Return a list of all users."""
  logger.info('list_users called')

  if context.request_context and context.request_context.request:
    if not validate_auth_header(context.request_context.request):
      return {'error': 'Unauthorized - invalid or missing token'}

  return {
      'users': [
          {'id': 'user1', 'name': 'Alice'},
          {'id': 'user2', 'name': 'Bob'},
      ]
  }


# Create custom FastAPI app to add auth middleware for list_tools
app = FastAPI()


@app.middleware('http')
async def auth_middleware(request: Request, call_next):
  """Middleware to validate auth on all MCP endpoints."""
  # Check if this is an MCP request
  if request.url.path.startswith('/mcp'):
    if not validate_auth_header(request):
      raise HTTPException(status_code=401, detail='Unauthorized')
  return await call_next(request)


if __name__ == '__main__':
  print(f'Starting OAuth Protected MCP server on http://localhost:3001')
  print(f'Expected token: Bearer {VALID_TOKEN}')
  print(
      'This server requires authentication for both tool listing and calling.'
  )

  # Run with streamable-http transport
  mcp.run(transport='streamable-http')
