# Copyright (c) 2025 Airbyte, Inc., all rights reserved.
"""MCP tools for connector registry operations.

This module provides MCP tools for interacting with the Airbyte connector registry
stored in Google Cloud Storage, including:
- Reading connector metadata and specs
- Listing connectors and versions
- Publishing metadata to the registry
"""

from __future__ import annotations

from typing import Annotated, Any

from fastmcp import FastMCP
from fastmcp_extensions import mcp_tool, register_mcp_tools
from pydantic import BaseModel, Field

from airbyte_ops_mcp.registry import (
    PROD_METADATA_SERVICE_BUCKET_NAME,
    ConnectorListResult,
    MetadataPublishResult,
    RegistryEntryResult,
    VersionListResult,
)
from airbyte_ops_mcp.registry.operations import (
    get_registry_entry,
    get_registry_spec,
    list_connector_versions,
    list_registry_connectors,
)
from airbyte_ops_mcp.registry.publish import (
    publish_connector_metadata as _publish_connector_metadata,
)


class RegistrySpecResult(BaseModel):
    """Result of reading a connector spec from GCS."""

    connector_name: str = Field(description="The connector technical name")
    version: str = Field(description="The version that was read")
    bucket_name: str = Field(description="The GCS bucket name")
    gcs_path: str = Field(description="The GCS path that was read")
    spec: dict[str, Any] = Field(description="The connector spec dictionary")


@mcp_tool(
    read_only=True,
    idempotent=True,
    open_world=True,
)
def get_connector_registry_entry(
    connector_name: Annotated[
        str,
        "The connector name (e.g., 'source-faker', 'destination-postgres')",
    ],
    version: Annotated[
        str,
        "Version to read (e.g., 'latest', '1.2.3'). Defaults to 'latest'.",
    ] = "latest",
) -> RegistryEntryResult:
    """Read a connector's metadata from the GCS registry.

    Returns the full metadata.yaml content for a connector at the specified version.
    Requires GCS_CREDENTIALS environment variable to be set.
    """
    bucket_name = PROD_METADATA_SERVICE_BUCKET_NAME
    metadata = get_registry_entry(
        connector_name=connector_name,
        bucket_name=bucket_name,
        version=version,
    )
    gcs_path = f"metadata/airbyte/{connector_name}/{version}/metadata.yaml"
    return RegistryEntryResult(
        connector_name=connector_name,
        version=version,
        bucket_name=bucket_name,
        gcs_path=gcs_path,
        metadata=metadata,
    )


@mcp_tool(
    read_only=True,
    idempotent=True,
    open_world=True,
)
def get_connector_registry_spec(
    connector_name: Annotated[
        str,
        "The connector name (e.g., 'source-faker', 'destination-postgres')",
    ],
    version: Annotated[
        str,
        "Version to read (e.g., 'latest', '1.2.3'). Defaults to 'latest'.",
    ] = "latest",
) -> RegistrySpecResult:
    """Read a connector's spec from the GCS registry.

    Returns the spec.json content for a connector at the specified version.
    Requires GCS_CREDENTIALS environment variable to be set.
    """
    bucket_name = PROD_METADATA_SERVICE_BUCKET_NAME
    spec = get_registry_spec(
        connector_name=connector_name,
        bucket_name=bucket_name,
        version=version,
    )
    gcs_path = f"metadata/airbyte/{connector_name}/{version}/spec.json"
    return RegistrySpecResult(
        connector_name=connector_name,
        version=version,
        bucket_name=bucket_name,
        gcs_path=gcs_path,
        spec=spec,
    )


@mcp_tool(
    read_only=True,
    idempotent=True,
    open_world=True,
)
def list_connectors_in_registry() -> ConnectorListResult:
    """List all connectors in the GCS registry.

    Scans the registry bucket to find all connectors that have metadata files.
    Requires GCS_CREDENTIALS environment variable to be set.
    """
    bucket_name = PROD_METADATA_SERVICE_BUCKET_NAME
    connectors = list_registry_connectors(bucket_name=bucket_name)
    return ConnectorListResult(
        bucket_name=bucket_name,
        connector_count=len(connectors),
        connectors=connectors,
    )


@mcp_tool(
    read_only=True,
    idempotent=True,
    open_world=True,
)
def list_connector_versions_in_registry(
    connector_name: Annotated[
        str,
        "The connector name (e.g., 'source-faker', 'destination-postgres')",
    ],
) -> VersionListResult:
    """List all versions of a connector in the GCS registry.

    Returns all published versions for a connector (excluding 'latest' and 'release_candidate').
    Requires GCS_CREDENTIALS environment variable to be set.
    """
    bucket_name = PROD_METADATA_SERVICE_BUCKET_NAME
    versions = list_connector_versions(
        connector_name=connector_name,
        bucket_name=bucket_name,
    )
    return VersionListResult(
        connector_name=connector_name,
        bucket_name=bucket_name,
        version_count=len(versions),
        versions=versions,
    )


@mcp_tool(
    read_only=False,
    destructive=False,
    idempotent=True,
    open_world=True,
)
def publish_connector_metadata(
    connector_name: Annotated[
        str,
        "The connector name (e.g., 'source-faker', 'destination-postgres')",
    ],
    metadata: Annotated[
        dict[str, Any],
        "The metadata dictionary to publish. Must contain a 'data' field.",
    ],
    version: Annotated[
        str,
        "The version to publish (e.g., '1.2.3')",
    ],
    update_latest: Annotated[
        bool,
        "If True, also update the 'latest' pointer. Defaults to True.",
    ] = True,
    dry_run: Annotated[
        bool,
        "If True, show what would be published without making changes.",
    ] = False,
) -> MetadataPublishResult:
    """Publish connector metadata to the GCS registry.

    Uploads metadata to a versioned path and optionally updates the 'latest' pointer.
    Uses MD5 hash comparison to avoid re-uploading unchanged files.
    Requires GCS_CREDENTIALS environment variable to be set.
    """
    return _publish_connector_metadata(
        connector_name=connector_name,
        metadata=metadata,
        bucket_name=PROD_METADATA_SERVICE_BUCKET_NAME,
        version=version,
        update_latest=update_latest,
        dry_run=dry_run,
    )


def register_registry_tools(app: FastMCP) -> None:
    """Register registry tools with the FastMCP app."""
    register_mcp_tools(app, mcp_module=__name__)
