/**
 * ADR-0027: org-scoped capability credential resolver. Reuses the ADR-0024
 * envelope decryption machinery (LocalSecretEnvelope) with
 * purpose="capability", distinct from the model-provider and Feishu
 * application connections. Fail-closed: no process-global fallback.
 *
 * Mirrors the Feishu application connection resolver shape, minus the
 * readiness probe (capability probes are per-capability and injected by the
 * adapter wiring, not this resolver).
 */
import type { PrismaClient } from "@prisma/client";
import { LocalSecretEnvelope, type SecretEnvelopeV1 } from "../security/secretEnvelope.js";
import {
  CapabilityConnectionUnavailable,
  type CapabilitySecretPayload,
  type CapabilityId,
} from "./types.js";

const CAPABILITY_PURPOSE = "capability";

export interface ResolvedCapabilityCredential extends CapabilitySecretPayload {
  readonly connectionId: string;
  readonly organizationId: string;
  readonly capabilityId: string;
}

/**
 * Resolve the active capability credential for an organization. Throws
 * CapabilityConnectionUnavailable when the org has no ACTIVE connection
 * (fail-closed, ADR-0024). Decrypted plaintext exists only in the returned
 * object for the duration of the capability call; it is never cached, logged,
 * or passed to the Agent process.
 */
export async function resolveCapabilityCredential(
  prisma: PrismaClient,
  secrets: LocalSecretEnvelope,
  input: { readonly organizationId: string; readonly capabilityId: CapabilityId },
): Promise<ResolvedCapabilityCredential> {
  const connection = await prisma.organizationCapabilityConnection.findFirst({
    where: {
      organizationId: input.organizationId,
      capabilityId: input.capabilityId,
      status: "ACTIVE",
    },
    include: { activeSecretVersion: true },
  });
  if (connection === null || connection.activeSecretVersion === null) {
    throw new CapabilityConnectionUnavailable(input.capabilityId, input.organizationId);
  }
  const version = connection.activeSecretVersion;
  const binding = {
    purpose: CAPABILITY_PURPOSE,
    organizationId: connection.organizationId,
    connectionId: connection.id,
    secretVersionId: version.id,
  };
  const payload = secrets.decryptJson<CapabilitySecretPayload>(binding, version.envelope as unknown as SecretEnvelopeV1);
  if (payload.schemaVersion !== 1) {
    throw new Error(`unsupported capability secret schemaVersion: ${payload.schemaVersion}`);
  }
  return {
    connectionId: connection.id,
    organizationId: connection.organizationId,
    capabilityId: connection.capabilityId,
    schemaVersion: 1,
    accessKeyId: payload.accessKeyId,
    accessKeySecret: payload.accessKeySecret,
    endpoint: payload.endpoint,
  };
}
