"""Shared wiring helpers for SQL-backed services.

These utilities keep individual service wiring modules small while preserving the
service-level "composition root" pattern (service chooses schema/gateway/client).
"""

from __future__ import annotations

from typing import Any

from relationalai.client.transports.sql import SqlClient
from relationalai.util.adapters import SyncToAsyncGatewayAdapter
from relationalai.util.noclose import NoClose


def require_sql_base(core: Any, *, service: str) -> Any:
    """Return the root client's configured SQL executor, or raise."""
    base = getattr(core, "sql_executor", None)
    if base is None:
        raise RuntimeError(f"{service} requires a SQL executor on Client/ClientSync.")
    return base


def require_app_name(core: Any, *, service: str) -> str:
    """Return the configured native app database name, or raise."""
    app_name = getattr(core, "app_name", None)
    if not app_name:
        raise ValueError(
            "\n".join(
                [
                    f"{service} requires an app name.",
                    "Ensure the Snowflake connection has `rai_app_name` set (native app database).",
                ]
            )
        )
    return str(app_name)


def build_sql_client(core: Any, *, error_handlers: Any) -> SqlClient:
    """Build a service-scoped `SqlClient` from the root client's base SQL executor."""
    base = require_sql_base(core, service="SQL backend")
    return SqlClient(
        session=base.session,
        middlewares=getattr(base, "middlewares", None),
        error_handlers=error_handlers,
        execution_metrics=getattr(base, "execution_metrics", None),
    )


def sync_gateway_to_async(gw_sync: Any) -> Any:
    """Wrap a sync gateway as an async gateway and disable closing."""
    gw = SyncToAsyncGatewayAdapter(gw_sync)
    return NoClose(gw)

