import type { UseCaseManifest } from "./define-feature";
import type { Instrumented, Captured } from "./brands";

/**
 * Type-level binding slot for production use cases. Derived from the manifest
 * entry: every binding must be Instrumented + Captured; mutating use cases
 * that declare audits additionally must be Audited. The Audited brand lives
 * in `@repo/core-audit` because the wrap helper that attaches it depends on
 * `IAuditLog` — feature packages import the merged slot type implicitly
 * by typing their bindings as `ProductionUseCase<I, O, AuthManifest["useCases"]["signIn"]>`.
 *
 * The Audited requirement is encoded conditionally so this type stays usable
 * without depending on core-audit. When `mutates: true` AND `audits` is
 * non-empty, the slot demands a marker type with a `__audited` flag; the
 * concrete `Audited<F>` from core-audit satisfies it.
 */
export type ProductionUseCase<I, O, M extends UseCaseManifest> =
  & Instrumented<(input: I) => Promise<O>>
  & Captured<(input: I) => Promise<O>>
  & (M["mutates"] extends true
      ? M["audits"]["length"] extends 0
        ? unknown
        : { readonly __audited: true }
      : unknown);
