"""外部系统 provider 注册表。

标准 OpenAPI 与 Streamable HTTP MCP 系统均通过数据库配置接入。
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Any

from .auth import ExternalAuthError, get_auth_strategy

@dataclass(frozen=True)
class ProviderSpec:
    provider: str
    title: str
    connector: str
    default_auth_type: str
    allowed_auth_types: tuple[str, ...]
    defaults: dict[str, Any]


_PROVIDERS = {
    "generic_openapi": ProviderSpec(
        provider="generic_openapi",
        title="通用 OpenAPI 系统",
        connector="openapi",
        default_auth_type="password_jwt",
        allowed_auth_types=("password_jwt", "api_key", "bearer_token"),
        defaults={
            "login_path": "/api/auth/token/",
            "username_field": "username",
            "password_field": "password",
            "token_field": "access",
            "auth_header_name": "Authorization",
            "auth_header_template": "Bearer {token}",
            "query_guidance": "",
            "recommended_operation_ids": [],
            "operation_mode": "query",
            "operation_policies": {},
        },
    ),
    "generic_mcp": ProviderSpec(
        provider="generic_mcp",
        title="通用 MCP 系统",
        connector="mcp",
        default_auth_type="password_jwt",
        allowed_auth_types=("password_jwt", "api_key", "bearer_token"),
        defaults={
            "login_path": "/api/auth/token/",
            "username_field": "username",
            "password_field": "password",
            "token_field": "access",
            "auth_header_name": "Authorization",
            "auth_header_template": "Bearer {token}",
            "query_guidance": "",
            "recommended_operation_ids": [],
            "operation_mode": "upstream_managed",
            "operation_policies": {},
        },
    ),
}


def get_provider(provider: str) -> ProviderSpec:
    result = _PROVIDERS.get((provider or "").strip())
    if result is None:
        raise ValueError(f"不支持的外部系统 provider: {provider}")
    return result


def provider_specs() -> tuple[ProviderSpec, ...]:
    return tuple(_PROVIDERS.values())


def merged_config(provider: str, config: dict[str, Any]) -> dict[str, Any]:
    spec = get_provider(provider)
    result = {**spec.defaults, **(config or {})}
    auth_type = str(result.get("auth_type") or spec.default_auth_type).strip()
    if auth_type not in spec.allowed_auth_types:
        raise ValueError(f"{spec.title} 不支持认证方式 {auth_type}")
    result["auth_type"] = auth_type
    return result


def credential_fields(provider: str, config: dict[str, Any]) -> list[dict[str, Any]]:
    merged = merged_config(provider, config)
    try:
        strategy = get_auth_strategy(merged["auth_type"])
    except ExternalAuthError as exc:
        raise ValueError(str(exc)) from exc
    return [field.as_dict() for field in strategy.credential_fields]
