/**
 * doc-ref.ts — shared document-reference schemas (D0090).
 *
 * `GeneralizedDocRefSchema` and `SourceLocatorSchema` are the single Zod
 * definitions for a robust document reference and its optional embedded
 * cross-source / cross-project locator. They are composed by every wrapper
 * that accepts document references:
 *
 * - `PipelineRequestSchema`  (the universal wire contract — API body, CLI
 *   `--config` JSON, repository_dispatch payload)
 * - `EvalConfigSchema`       (the `--config` developer config wrapper, D0060)
 *
 * Both schemas `satisfies z.ZodType<…>` against the independently-authored
 * domain types in `@sanity/ailf-shared` / `../types/generalized-task.ts`, so
 * backend/wire drift is a build error (D0045) and there is exactly one union
 * — no per-wrapper duplication.
 *
 * This module lives in core because both wrappers live in core; the domain
 * types it asserts against live one layer down in shared.
 */
import { z } from "zod";
// ---------------------------------------------------------------------------
// Source locator — tier-2 cross-source / cross-project pinning (D0062 / D0063)
// ---------------------------------------------------------------------------
/**
 * Embedded retrieval contract for a `GeneralizedDocRef` (D0090 tier 2).
 *
 * `SourceLocator = SanityContentLakeLocator | GoogleDriveLocator |
 * SanityCanvasLocator`. Authored independently in `@sanity/ailf-shared`; this
 * schema asserts `satisfies z.ZodType<SourceLocator>` so backend/wire drift
 * is a build error (D0045). Kept permissive on the optional fields (no
 * `.url()` on the Content Lake `url`, since a locator may carry an internal
 * handle), but the required identity fields (`projectId` + `dataset` +
 * `documentId` for Content Lake; `fileId` for Drive; `environment` +
 * `organizationId` + `resourceId` + `documentId` for Canvas) are enforced.
 */
export const SourceLocatorSchema = z.union([
    z.object({
        kind: z.literal("sanity-content-lake"),
        projectId: z.string().min(1),
        dataset: z.string().min(1),
        organizationId: z.string().optional(),
        url: z.string().optional(),
        resource: z.literal("document").optional(),
        documentId: z.string().min(1),
        documentType: z.string().optional(),
        revision: z.string().optional(),
        perspective: z.string().optional(),
    }),
    z.object({
        kind: z.literal("google-drive"),
        fileId: z.string().min(1),
        revision: z.string().optional(),
    }),
    z.object({
        kind: z.literal("sanity-canvas"),
        environment: z.enum(["production", "staging"]),
        organizationId: z.string().min(1),
        resourceId: z.string().min(1),
        documentId: z.string().min(1),
        revision: z.string().optional(),
    }),
]);
// ---------------------------------------------------------------------------
// Generalized doc reference — polymorphic resolution by key presence
// ---------------------------------------------------------------------------
/**
 * `IdDocRef` is listed FIRST so an entry carrying both `id` and
 * `path`/`slug` matches it (preserving id/slug/path) instead of being
 * narrowed to `PathDocRef`/`SlugDocRef`. The `_id` is authoritative;
 * slug/path are informational only.
 *
 * Every arm carries an optional `locator` ({@link SourceLocatorSchema}) for
 * tier-2 cross-source / cross-project pinning (D0090). It stays optional so
 * every existing bare reference validates unchanged.
 */
export const GeneralizedDocRefSchema = z.union([
    z.object({
        id: z.string().min(1),
        slug: z.string().optional(),
        path: z.string().optional(),
        reason: z.string().optional(),
        locator: SourceLocatorSchema.optional(),
    }),
    z.object({
        path: z.string().min(1),
        reason: z.string().optional(),
        locator: SourceLocatorSchema.optional(),
    }),
    z.object({
        slug: z.string().min(1),
        reason: z.string().optional(),
        locator: SourceLocatorSchema.optional(),
    }),
    z.object({
        perspective: z.string().min(1),
        reason: z.string().optional(),
        locator: SourceLocatorSchema.optional(),
    }),
]);
