"""Example usage of MCP client and server."""

import asyncio
from typing import Any

from fastapi import HTTPException, status
from mcp.server.fastmcp import FastMCP
from pydantic import BaseModel, Field

from ..openrouter import OpenRouterClient
from .client import MCPClient
from .server import MCPServer, OAuth2Configuration


# Create a FastMCP instance for this module
mcp = FastMCP("weather-service")


# Define input/output models
class WeatherInput(BaseModel):
    location: str
    units: str = "celsius"  # Default to celsius, can be "fahrenheit" or "celsius"


class WeatherOutput(BaseModel):
    location: str
    temperature: float
    units: str
    condition: str
    humidity: float


class LastOrdersInput(BaseModel):
    limit: int = 5
    __auth__: dict[str, object] | None = Field(
        default=None,
        description="Authentication context injected by the MCP server",
    )


@mcp.tool()
async def get_weather(input: WeatherInput) -> dict[str, Any]:
    """Get weather information for a location."""
    # This is a mock implementation
    temperature = 20 if input.units == "celsius" else 68

    return {
        "location": input.location,
        "temperature": temperature,
        "units": input.units,
        "condition": "sunny",
        "humidity": 65,
    }


@mcp.tool()
async def get_last_orders(input: LastOrdersInput) -> list[dict[str, Any]]:
    """Get the last orders of the currently authenticated customer."""
    limit = max(1, min(input.limit, 20))

    auth_context = input.__auth__ or {}
    access_token = auth_context.get("access_token")
    scopes = auth_context.get("scopes", [])
    user_id = auth_context.get("user_id")

    # In a real implementation you would now use access_token / user_id
    # to call your backend or Shopware instance. Here we just include them
    # in the mock response to demonstrate that they are available.

    return [
        {
            "orderNumber": f"ORDER-{index}",
            "totalAmount": 123.45,
            "currency": "EUR",
            "userId": user_id,
            "scopes": scopes,
            "accessToken": access_token,
        }
        for index in range(1, limit + 1)
    ]


async def validate_oauth2_token(token: str, required_scopes: list[str]) -> dict[str, object]:
    """Example OAuth2 handler used by the MCP server.

    In a real implementation you would validate the access token against your
    identity provider (introspection or JWT validation) and check the scopes.
    """
    if token != "dummy-access-token":
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid access token",
        )

    missing_scopes = [
        scope for scope in required_scopes
        if scope not in {"orders:read"}
    ]
    if missing_scopes:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail=f"Missing required scopes: {', '.join(missing_scopes)}",
        )

    # Return an authentication context that will be injected into the tool input.
    return {
        "access_token": token,
        "scopes": required_scopes,
        "user_id": "customer-123",
    }


async def main():
    # Create the MCP server with OAuth2 support
    oauth2_config = OAuth2Configuration(
        issuer="https://auth.example.com",
        authorization_endpoint="https://auth.example.com/oauth/authorize",
        token_endpoint="https://auth.example.com/oauth/token",
        jwks_uri="https://auth.example.com/.well-known/jwks.json",
        scopes_supported=["orders:read"],
    )
    server = MCPServer(
        "weather-service",
        oauth2_configuration=oauth2_config,
        oauth2_handler=validate_oauth2_token,
    )

    # Register the tools with the MCP server
    await server.add_tool(get_weather)
    await server.add_tool(
        get_last_orders,
        security_schemes=[
            {
                "type": "oauth2",
                "scopes": ["orders:read"],
            }
        ],
    )

    # Create the OpenRouter client
    openrouter_client = OpenRouterClient(token="your-api-key")

    # Create the MCP client
    mcp_client = MCPClient(openrouter_client)

    # Register the MCP server
    await mcp_client.register_mcp_server(
        name="weather-service",
        base_url="http://localhost:8000",
    )

    # Use the tool in a chat
    messages = [
        {
            "role": "user",
            "content": "What's the weather like in New York?",
        }
    ]
    response = await mcp_client.chat(messages)
    print(response.choices[0].message.content)

    # Use the weather tool with structured output
    response = await mcp_client.parse(messages, WeatherOutput)
    weather_info = response.choices[0].message.parsed
    print(f"Location: {weather_info.location}")
    print(f"Temperature: {weather_info.temperature}°{weather_info.units.upper()}")
    print(f"Condition: {weather_info.condition}")
    print(f"Humidity: {weather_info.humidity}%")


if __name__ == "__main__":
    asyncio.run(main())