"""
ROUTER SETTINGS MANAGEMENT

Endpoints for accessing router configuration and metadata

GET /router/settings - Get router configuration including available routing strategies
GET /router/fields - Get router settings field definitions without values (for UI rendering)
"""

import inspect
from typing import Any, Dict, List, get_args

from fastapi import APIRouter, Depends
from pydantic import BaseModel, Field

from litellm._logging import verbose_proxy_logger
from litellm.proxy._types import UserAPIKeyAuth
from litellm.proxy.auth.user_api_key_auth import user_api_key_auth
from litellm.router import Router
from litellm.types.management_endpoints import (
    ROUTER_SETTINGS_FIELDS,
    ROUTING_STRATEGY_DESCRIPTIONS,
    RouterSettingsField,
)

router = APIRouter()


class RouterSettingsResponse(BaseModel):
    fields: List[RouterSettingsField] = Field(
        description="List of all configurable router settings with metadata"
    )
    current_values: Dict[str, Any] = Field(
        description="Current values of router settings"
    )
    routing_strategy_descriptions: Dict[str, str] = Field(
        description="Descriptions for each routing strategy option"
    )


class RouterFieldsResponse(BaseModel):
    fields: List[RouterSettingsField] = Field(
        description="List of all configurable router settings with metadata (without field values)"
    )
    routing_strategy_descriptions: Dict[str, str] = Field(
        description="Descriptions for each routing strategy option"
    )


def _get_routing_strategies_from_router_class() -> List[str]:
    """
    Dynamically extract routing strategies from the Router class __init__ method.
    """
    # Get the __init__ signature
    sig = inspect.signature(Router.__init__)

    # Get the routing_strategy parameter
    routing_strategy_param = sig.parameters.get("routing_strategy")

    if routing_strategy_param and routing_strategy_param.annotation:
        # Extract Literal values using get_args
        literal_values = get_args(routing_strategy_param.annotation)
        if literal_values:
            return list(literal_values)

    raise ValueError("Unable to extract routing strategies from Router class")


@router.get(
    "/router/settings",
    tags=["Router Settings"],
    dependencies=[Depends(user_api_key_auth)],
    response_model=RouterSettingsResponse,
)
async def get_router_settings(
    user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),
):
    """
    Get router configuration and available settings.

    Returns:
    - fields: List of all configurable router settings with their metadata (type, description, default, options)
              The routing_strategy field includes available options extracted from the Router class
    - current_values: Current values of router settings from config
    """
    from litellm.proxy.proxy_server import llm_router, proxy_config

    try:
        # Get available routing strategies dynamically from Router class
        available_routing_strategies = _get_routing_strategies_from_router_class()

        # Get router settings fields from types file
        router_fields = [
            field.model_copy(deep=True) for field in ROUTER_SETTINGS_FIELDS
        ]

        # Populate routing_strategy field with available options and descriptions
        for field in router_fields:
            if field.field_name == "routing_strategy":
                field.options = available_routing_strategies
                break

        # Try to get router settings from config
        config = await proxy_config.get_config()
        router_settings_from_config = config.get("router_settings", {})

        current_values: Dict[str, Any] = {}
        if llm_router is not None:
            # Router exposes routing groups as private `_routing_groups`; the
            # generic `hasattr` loop below would miss them.
            current_values["routing_groups"] = [
                group.model_dump() for group in llm_router._routing_groups.values()
            ]
            for field in router_fields:
                if field.field_name == "routing_groups":
                    continue
                if hasattr(llm_router, field.field_name):
                    value = getattr(llm_router, field.field_name)
                    current_values[field.field_name] = value

        # Merge with config values (config takes precedence)
        current_values.update(router_settings_from_config)

        # Update field values with current values
        for field in router_fields:
            if field.field_name in current_values:
                field.field_value = current_values[field.field_name]

        return RouterSettingsResponse(
            fields=router_fields,
            current_values=current_values,
            routing_strategy_descriptions=ROUTING_STRATEGY_DESCRIPTIONS,
        )
    except Exception as e:
        verbose_proxy_logger.error(f"Error fetching router settings: {str(e)}")
        raise


@router.get(
    "/router/fields",
    tags=["Router Settings"],
    dependencies=[Depends(user_api_key_auth)],
    response_model=RouterFieldsResponse,
)
async def get_router_fields(
    user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),
):
    """
    Get router settings field definitions without values.

    Returns only the field metadata (type, description, default, options) without
    populating field_value. This is useful for UI components that need to know
    what fields to render, but will get the actual values from a different endpoint.

    Returns:
    - fields: List of all configurable router settings with their metadata (type, description, default, options)
              The routing_strategy field includes available options extracted from the Router class
              Note: field_value will be None for all fields
    - routing_strategy_descriptions: Descriptions for each routing strategy option
    """
    try:
        # Get available routing strategies dynamically from Router class
        available_routing_strategies = _get_routing_strategies_from_router_class()

        # Get router settings fields from types file
        router_fields = [
            field.model_copy(deep=True) for field in ROUTER_SETTINGS_FIELDS
        ]

        # Populate routing_strategy field with available options
        for field in router_fields:
            if field.field_name == "routing_strategy":
                field.options = available_routing_strategies
                break

        # Ensure field_value is None for all fields (don't populate values)
        for field in router_fields:
            field.field_value = None

        return RouterFieldsResponse(
            fields=router_fields,
            routing_strategy_descriptions=ROUTING_STRATEGY_DESCRIPTIONS,
        )
    except Exception as e:
        verbose_proxy_logger.error(f"Error fetching router fields: {str(e)}")
        raise
