"""Resolves a project's connector credentials into env bindings for a deployed function.

A Function Library manifest's ``required_integrations`` (e.g. ``["stripe"]``) says the
function needs that connector configured on the project. This module looks up the
project's active connection for each required connector, decrypts its secrets, and
turns both config and secrets into Worker bindings named ``{CONNECTOR_KEY}_{FIELD_KEY}``
(uppercased) — e.g. the stripe connector's ``secret_key`` field becomes
``STRIPE_SECRET_KEY``, matching what seeds like ``stripe-create-checkout.yaml`` already
declare in ``required_secrets``.
"""
from __future__ import annotations

from uuid import UUID

from src.core.exceptions import ConflictError, NotFoundError
from src.core.security.encryption import decrypt_value
from src.domain.connectors.catalog import get_connector
from src.domain.connectors.repository import ConnectorRepository


async def has_active_connector_connection(
    connector_repo: ConnectorRepository,
    project_id: UUID,
    connector_key: str,
) -> bool:
    """Lightweight prerequisite check — does this project have an active connection?

    Same lookup as resolve_connector_bindings, without decrypting secrets, for
    callers (e.g. feature-pack prerequisite checks) that only need a yes/no.
    """
    catalog_row = await connector_repo.get_connector_by_key(connector_key)
    if not catalog_row:
        return False
    connections = await connector_repo.list_connections_for_project(project_id)
    return any(c.connector_id == catalog_row.id and c.status == "active" for c in connections)


async def resolve_connector_bindings(
    connector_repo: ConnectorRepository,
    project_id: UUID,
    required_integrations: list[str],
) -> tuple[dict[str, str], dict[str, str]]:
    """Return ``(plain_env_vars, secret_env_vars)`` for every required connector.

    Raises :class:`NotFoundError` if a required connector has no active connection on
    this project — deploy should fail with a clear message rather than ship a function
    that will error on first invocation.
    """
    env_vars: dict[str, str] = {}
    secrets: dict[str, str] = {}

    for key in required_integrations:
        cdef = get_connector(key)
        if not cdef:
            raise ConflictError(f"Unknown connector {key!r} required by this function")

        catalog_row = await connector_repo.get_connector_by_key(key)
        connections = await connector_repo.list_connections_for_project(project_id)
        matching = [
            c
            for c in connections
            if catalog_row and c.connector_id == catalog_row.id and c.status == "active"
        ]
        if not matching:
            raise NotFoundError(
                f"This function requires a '{cdef.name}' connection, but none is "
                f"configured for this project. Add one under Connectors first."
            )
        connection = min(matching, key=lambda c: c.created_at)

        prefix = key.upper()
        for field_key, value in (connection.config_json or {}).items():
            if value is not None:
                env_vars[f"{prefix}_{field_key.upper()}"] = str(value)
        for field_key, enc_value in (connection.secrets_enc or {}).items():
            secrets[f"{prefix}_{field_key.upper()}"] = decrypt_value(enc_value)

    return env_vars, secrets
