/**
 * ADR-0027: External capability types shared across the adapter layer.
 *
 * A capability is a platform-registered, org-enabled document/media transform
 * invoked as a side effect of an AgentRun. The adapter resolves the org's
 * active capability connection, calls the backing service via an injectable
 * client, writes output into the run's workspace (AgentSurface, ADR-0018),
 * and records consumption on a UsageFact (ADR-0026).
 */
import type { PrismaClient, Prisma } from "@prisma/client";

/** Stable capability identifiers registered with the platform (ADR-0027). */
export const CAPABILITY_IDS = [
  "pdf_to_md_bundle",
  "audio_video_to_text",
] as const;

export type CapabilityId = (typeof CAPABILITY_IDS)[number];

/** Non-token metering unit for a capability (ADR-0026/0027). */
export interface CapabilityDescriptor {
  readonly id: CapabilityId;
  readonly meteringUnit: string;
}

/** Known capabilities and their metering units. Code-level registry. */
export const CAPABILITIES: Readonly<Record<CapabilityId, CapabilityDescriptor>> = {
  pdf_to_md_bundle: { id: "pdf_to_md_bundle", meteringUnit: "pages" },
  audio_video_to_text: { id: "audio_video_to_text", meteringUnit: "audio_seconds" },
};

/** Input passed to a capability adapter invocation. */
export interface CapabilityInvocationInput {
  readonly runId: string;
  readonly organizationId: string;
  readonly projectId: string;
  /** Absolute workspace dir of the run's project (ADR-0018 surface root). */
  readonly workspaceDir: string;
  /** Workspace-relative path to the input file (PDF, audio, …). */
  readonly inputPath: string;
  /** Workspace-relative directory to write outputs into. Created if absent. */
  readonly outputDir: string;
  /** Prisma client for UsageFact writes. */
  readonly prisma: PrismaClient;
}

/** A successfully produced output artifact (file written into workspace). */
export interface CapabilityOutputArtifact {
  /** Workspace-relative path of the written artifact. */
  readonly path: string;
  readonly kind: "markdown" | "image" | "metadata" | "other";
}

/** Consumption recorded for one invocation (written to UsageFact). */
export interface CapabilityConsumption {
  /** The backing service provider id (e.g. "mineru", "openai_whisper"). */
  readonly provider: string;
  /** Model id if the service reports one; null for non-model services. */
  readonly model: string | null;
  readonly inputTokens: number | null;
  readonly outputTokens: number | null;
  /** Non-token meter (page count, audio seconds). */
  readonly quantity: number;
  readonly unit: string;
  /** USD cost if the service reported one; null = unknown (ADR-0022). */
  readonly costUsd: number | null;
  /** External request id for reconciliation. */
  readonly correlationId: string | null;
}

/** Result of a successful capability invocation. */
export interface CapabilityInvocationResult {
  readonly artifacts: readonly CapabilityOutputArtifact[];
  readonly consumption: CapabilityConsumption;
}

/** A capability adapter: resolves credentials, calls the service, writes output. */
export interface CapabilityAdapter {
  readonly capabilityId: CapabilityId;
  invoke(input: CapabilityInvocationInput): Promise<CapabilityInvocationResult>;
}

/** Decrypted capability credential (CapabilitySecretPayloadV1, ADR-0027).
 * Alibaba Cloud Document Mind (docmind) uses AccessKey ID + Secret + endpoint. */
export interface CapabilitySecretPayload {
  readonly schemaVersion: 1;
  readonly accessKeyId: string;
  readonly accessKeySecret: string;
  readonly endpoint: string;
}

/** Thrown when an org has no ACTIVE capability connection (fail-closed, ADR-0024). */
export class CapabilityConnectionUnavailable extends Error {
  constructor(readonly capabilityId: string, readonly organizationId: string) {
    super(`no ACTIVE capability connection for ${capabilityId} in org ${organizationId}`);
    this.name = "CapabilityConnectionUnavailable";
  }
}

/** Prisma transaction client type alias (for resolver signatures). */
export type TxClient = Prisma.TransactionClient;
