# SPDX-FileCopyrightText: 2025 CoreWeave, Inc.
# SPDX-License-Identifier: Apache-2.0
# SPDX-PackageName: cwsandbox-client

"""gRPC channel management for CWSandbox SDK.

This module provides utilities for creating and managing gRPC channels
to communicate with the CWSandbox backend.

Generated SDK imports:
- from cwsandbox._proto import atc_pb2_grpc (ATCServiceStub)
- from cwsandbox._proto import streaming_pb2_grpc (ATCStreamingServiceStub)
"""

from __future__ import annotations

from urllib.parse import urlparse

import grpc
import grpc.aio


def parse_grpc_target(base_url: str) -> tuple[str, bool]:
    """Parse a URL into a gRPC target and security flag.

    Args:
        base_url: HTTP(S) URL to parse (e.g., "https://atc.cw-sandbox.com")

    Returns:
        Tuple of (target, is_secure) where:
        - target: "host:port" string for gRPC channel
        - is_secure: True for HTTPS, False for HTTP

    Raises:
        ValueError: If URL scheme is not http/https or if URL has a path
    """
    parsed = urlparse(base_url)

    if parsed.scheme not in ("http", "https"):
        raise ValueError(f"URL must use http or https scheme, got: {parsed.scheme!r}")

    if parsed.path and parsed.path != "/":
        raise ValueError(f"gRPC does not support URL paths, got: {parsed.path!r}")

    is_secure = parsed.scheme == "https"

    host = parsed.hostname
    if not host:
        raise ValueError(f"URL must have a hostname: {base_url!r}")

    if parsed.port:
        port = parsed.port
    else:
        port = 443 if is_secure else 80

    target = f"{host}:{port}"
    return target, is_secure


def create_channel(
    target: str,
    is_secure: bool,
) -> grpc.aio.Channel:
    """Create a gRPC async channel.

    Args:
        target: gRPC target in "host:port" format
        is_secure: If True, use TLS; if False, use insecure channel

    Returns:
        An async gRPC channel
    """
    if is_secure:
        credentials = grpc.ssl_channel_credentials()
        return grpc.aio.secure_channel(target, credentials)
    else:
        return grpc.aio.insecure_channel(target)
