/**
 * GROQ queries scoped to each documentation feature area.
 *
 * Schema notes (dataset: gabe-wyatt-doc-plat-dev-2026-01-05):
 *
 *   _type == "article"        — 614 documentation articles
 *   primarySection             — reference to a docsNavSection
 *   content[]                  — Portable Text rich-text field
 *   slug.current               — URL slug
 *
 *   Code blocks in `content`:
 *     _type == "codeBlock" → blocks[].code.code, blocks[].code.language, blocks[].filename
 *
 *   Sections are _type == "docsNavSection" with slug.current.
 *
 * Each query joins through primarySection._ref to the relevant
 * docsNavSection IDs and returns a consistent projection.
 */
import { buildDocsByIdsQuery } from "./document-renderers.js";
// ---------------------------------------------------------------------------
// Section IDs (docsNavSection._id values)
// ---------------------------------------------------------------------------
const SECTION_IDS = {
    apisAndSdks: "bc30def4-a95a-44ef-a4d4-cacb4d55e816",
    appSdk: "d01fba8e-da8d-40ba-a09f-1a5f000de4a4",
    astroQuickstart: "73bebb61-e508-42b7-b44b-c4703ae42d01",
    computeAndAi: "3024ce79-c196-49ee-a237-a327d6a6348f",
    contentLake: "60a6bcb5-9706-4cab-9153-57725e28f4d0",
    developerGuides: "ea6b80fa-d0d2-4daa-8220-eb8abdcc9deb",
    gettingStarted: "f78cfeb7-ebc4-4684-b7fa-99c7ae528e68",
    libraries: "4551373a-8764-4da3-ac65-406d7dfb96e2",
    nextJsQuickstart: "6208dff1-bba7-487a-a6bb-a0ffccb5846c",
    nuxtJsQuickstart: "b2c937d0-34b3-435e-818b-d0c8520ea9b8",
    reactRouterQuickstart: "e223241c-e207-41e0-8e12-f80e78203cf1",
    studio: "d67e3879-0342-4a80-8a2d-e35908df35cc",
    visualEditing: "4e0ef463-01e2-48db-9a31-38b3912ececd",
};
// ---------------------------------------------------------------------------
// Shared projection
// ---------------------------------------------------------------------------
/**
 * Standard projection applied to every article query.
 *
 * Returns the raw Portable Text `content` array so that the Node-side
 * converter (@portabletext/markdown) can produce well-structured Markdown
 * with headings, code fences, tables, callouts, etc.
 *
 * `_id`, `_type`, and `_rev` are projected so a result satisfies the
 * `DocumentForRender` shape and can dispatch through the renderer
 * registry uniformly with id-ref-resolved docs (W0197).
 */
const ARTICLE_PROJECTION = `{
  _id,
  _type,
  _rev,
  title,
  description,
  "slug": slug.current,
  "section": primarySection->{ "slug": slug.current, title },
  "content": content[] {
    // Pass through all standard blocks unchanged
    _type != "docsCardCollection" => { ... },
    // Resolve references inside card collections so we get titles/slugs
    _type == "docsCardCollection" => {
      ...,
      cards[] {
        ...,
        "resolvedTitle": reference->title,
        "resolvedSlug": reference->slug.current
      }
    }
  }
}`;
// ---------------------------------------------------------------------------
// Feature-area queries
// ---------------------------------------------------------------------------
export const FEATURE_AREA_QUERIES = {
    /**
     * Other Frameworks — Nuxt, React Router/Remix, Astro
     */
    frameworks: `
    *[_type == "article"
      && !(_id in path("drafts.**"))
      && (
        primarySection._ref in [
          "${SECTION_IDS.nuxtJsQuickstart}",
          "${SECTION_IDS.reactRouterQuickstart}",
          "${SECTION_IDS.astroQuickstart}"
        ]
        || (primarySection._ref == "${SECTION_IDS.developerGuides}"
            && (title match "Remix*" || title match "Nuxt*"
                || title match "Astro*" || title match "SvelteKit*"))
      )
    ] ${ARTICLE_PROJECTION}
  `,
    /**
     * Functions / Compute / AI — serverless functions, webhooks
     * Section: "Compute and AI" (12 articles)
     */
    functions: `
    *[_type == "article"
      && primarySection._ref == "${SECTION_IDS.computeAndAi}"
      && !(_id in path("drafts.**"))
    ] ${ARTICLE_PROJECTION}
  `,
    /**
     * GROQ Query Language — introduction, syntax, joins, filtering, projections
     * Combines: Content Lake section GROQ articles + Developer Guides articles
     * about querying + title-matched GROQ articles across all sections.
     */
    groq: `
    *[_type == "article"
      && !(_id in path("drafts.**"))
      && (
        primarySection._ref == "${SECTION_IDS.contentLake}"
        || primarySection._ref == "${SECTION_IDS.developerGuides}"
      )
      && (
        title match "GROQ*"
        || title match "*GROQ*"
        || title match "Query*"
        || title match "How Queries*"
        || slug.current match "groq-*"
        || slug.current match "query-*"
        || slug.current match "how-queries-*"
        || slug.current match "paginating-with-groq"
        || slug.current match "high-performance-groq"
      )
    ] ${ARTICLE_PROJECTION}
  `,
    /**
     * Next.js integration + Live Content API
     * Combines: Next.js quickstart section + developer-guide articles
     * mentioning Next.js or Live Content.
     */
    "nextjs-live": `
    *[_type == "article"
      && !(_id in path("drafts.**"))
      && (
        primarySection._ref == "${SECTION_IDS.nextJsQuickstart}"
        || (primarySection._ref == "${SECTION_IDS.developerGuides}"
            && (title match "Next*" || title match "*Live*"))
      )
    ] ${ARTICLE_PROJECTION}
  `,
    /**
     * Studio Setup & Customization
     * Section: "Studio" (116 articles)
     */
    "studio-setup": `
    *[_type == "article"
      && primarySection._ref == "${SECTION_IDS.studio}"
      && !(_id in path("drafts.**"))
    ] ${ARTICLE_PROJECTION}
  `,
    /**
     * Visual Editing — Presentation tool, overlays, live preview
     * Section: "Visual Editing" (24 articles)
     */
    "visual-editing": `
    *[_type == "article"
      && primarySection._ref == "${SECTION_IDS.visualEditing}"
      && !(_id in path("drafts.**"))
    ] ${ARTICLE_PROJECTION}
  `,
};
export const ALL_FEATURE_AREAS = Object.keys(FEATURE_AREA_QUERIES);
// ---------------------------------------------------------------------------
// Single-article query (used by canonical doc fetcher)
// ---------------------------------------------------------------------------
/**
 * Fetch a single article by its slug.
 * Returns the same projection shape as the feature-area queries.
 */
export const ARTICLE_BY_SLUG_QUERY = `
  *[_type == "article"
    && slug.current == $slug
    && !(_id in path("drafts.**"))
  ][0] ${ARTICLE_PROJECTION}
`;
/**
 * Fetch all published articles (for full-corpus generation).
 */
export const ALL_ARTICLES_QUERY = `
  *[_type == "article"
    && !(_id in path("drafts.**"))
  ] | order(primarySection->slug.current, title) ${ARTICLE_PROJECTION}
`;
// ---------------------------------------------------------------------------
// Perspective diffing queries
// ---------------------------------------------------------------------------
/**
 * Fetch article metadata for a list of slugs.
 *
 * Returns lightweight metadata (slug + _rev) for comparison between
 * published and perspective states. The _rev field changes when a document
 * is modified, making it an efficient diff signal.
 *
 * Usage: client.fetch(ARTICLES_METADATA_BY_SLUGS_QUERY, { slugs: ["slug-a", "slug-b"] })
 */
export const ARTICLES_METADATA_BY_SLUGS_QUERY = `
  *[_type == "article"
    && slug.current in $slugs
    && !(_id in path("drafts.**"))
  ] {
    "slug": slug.current,
    "sectionSlug": primarySection->slug.current,
    _id,
    _rev,
    title
  }
`;
/**
 * Fetch lightweight metadata for a list of document IDs — no `_type` filter.
 *
 * The type-agnostic sibling of ARTICLES_METADATA_BY_SLUGS_QUERY, keyed on the
 * document `_id` instead of the article `slug`. The release diff must compare a
 * document to a different VERSION of itself; the slug is article-only and not
 * unique, and a raw prefixed `_id` differs across versions. The document key
 * (`{anchor + base documentId}`, per D0084 / `baseDocumentId`) is the correct
 * cross-version join, so this query keys on `_id` and returns the
 * document/version-key fields (`_id`, `_type`, `_rev`) plus the editorial
 * `slug` for display (null for typeless docs).
 *
 * Does NOT filter `!(_id in path("drafts.**"))`: like the other id-keyed
 * queries it is designed for a perspective-enabled client where draft/version
 * filtering is handled at the client level, and `$ids` is an explicit set.
 *
 * Usage: client.fetch(DOCS_METADATA_BY_IDS_QUERY, { ids: ["doc-a", "doc-b"] })
 *
 * @param $ids — array of document ID strings
 */
export const DOCS_METADATA_BY_IDS_QUERY = `
  *[_id in $ids] {
    _id,
    _type,
    _rev,
    "slug": slug.current
  }
`;
/**
 * Fetch a single article by its slug — identical to ARTICLE_BY_SLUG_QUERY
 * but designed to be called with a perspective-enabled client.
 *
 * Returns the full article projection for content comparison.
 */
export const ARTICLE_BY_SLUG_WITH_PERSPECTIVE_QUERY = `
  *[_type == "article"
    && slug.current == $slug
  ][0] ${ARTICLE_PROJECTION}
`;
// ---------------------------------------------------------------------------
// Document ID queries
// ---------------------------------------------------------------------------
/**
 * Fetch articles by their document IDs.
 *
 * Does NOT include the `!(_id in path("drafts.**"))` filter because this
 * query is designed for use with perspective-enabled clients where draft
 * filtering is handled at the client level.
 *
 * @param $ids — array of document ID strings
 */
export const ARTICLES_BY_IDS_QUERY = `
  *[_type == "article"
    && _id in $ids
  ] ${ARTICLE_PROJECTION}
`;
/**
 * Fetch arbitrary documents by their `_id` — no `_type` filter.
 *
 * Used by id-ref resolution (and the type-agnostic perspective-ref content
 * path) so authors can pin any document type (`article`, `typesReference`,
 * `openApiReference`, `marketingPage`, `glossaryEntry`, …), not just articles.
 *
 * **Derived, not hand-written (D0085).** The per-`_type` projection branches
 * and the `!(_type in [...])` exclusion list are assembled from the renderer
 * registry by {@link buildDocsByIdsQuery}: each registered renderer declares
 * the projection it needs, and the exclusion list is the shared
 * `CANONICAL_DOC_TYPES_GROQ`. A renderer added to the registry gains its branch
 * and extends the exclusion automatically, so the projection cannot silently
 * drift from the registry (a type added to the registry but forgotten in the
 * exclusion list previously fell to the catch-all and lost its renderer's
 * fields). The default renderer's `{ ... }` projection is the catch-all, so any
 * unregistered type still resolves with best-effort content (W0195).
 *
 * Does NOT include the `!(_id in path("drafts.**"))` filter — id-ref
 * resolution is intentional, drafts are queryable when perspective is
 * draft-enabled, and authors are expected to pin published `_id`s.
 *
 * @param $ids — array of document ID strings
 * @see packages/eval/src/sanity/document-renderers.ts — buildDocsByIdsQuery
 */
export const DOCS_BY_IDS_QUERY = buildDocsByIdsQuery();
/**
 * Fetch a single article by its document ID.
 *
 * Does NOT include the `!(_id in path("drafts.**"))` filter because this
 * query is designed for use with perspective-enabled clients where draft
 * filtering is handled at the client level.
 *
 * @param $id — document ID string
 */
export const ARTICLE_BY_ID_QUERY = `
  *[_type == "article"
    && _id == $id
  ][0] ${ARTICLE_PROJECTION}
`;
// ---------------------------------------------------------------------------
// Path-based resolution queries
// ---------------------------------------------------------------------------
/**
 * Resolve an article slug from a URL path segment.
 *
 * Handles simple paths (just the slug, e.g., "webhooks") by matching
 * against slug.current. Returns the slug for downstream slug-based fetching.
 *
 * @param $slug — the path segment (article slug)
 */
export const ARTICLE_SLUG_BY_PATH_QUERY = `
  *[_type == "article"
    && slug.current == $slug
    && !(_id in path("drafts.**"))
  ][0] { "slug": slug.current, "sectionSlug": primarySection->slug.current }
`;
/**
 * Resolve an article slug from a section-qualified path.
 *
 * Handles compound paths like "content-lake/webhooks" where the first
 * segment is the section slug and the last segment is the article slug.
 * This disambiguates articles that share a slug across different sections.
 *
 * @param $articleSlug — the article slug (last path segment)
 * @param $sectionSlug — the section slug (first path segment)
 */
export const ARTICLE_SLUG_BY_SECTION_PATH_QUERY = `
  *[_type == "article"
    && slug.current == $articleSlug
    && primarySection->slug.current == $sectionSlug
    && !(_id in path("drafts.**"))
  ][0] { "slug": slug.current }
`;
// ---------------------------------------------------------------------------
// Content Release — perspective ref expansion
// ---------------------------------------------------------------------------
/**
 * Find all article documents that are versioned within a content release.
 *
 * Uses `sanity::partOfRelease()` to identify documents that have versions
 * in the specified release. Must be called with a perspective-enabled
 * client so the versioned content is visible.
 *
 * Returns the original document IDs (not the `versions.*` prefixed ones)
 * because the perspective client transparently resolves versioned docs
 * back to their canonical shape.
 *
 * @param $releaseId — the release ID (e.g., "ailf-scenario-01-test")
 */
export const ARTICLES_IN_RELEASE_QUERY = `
  *[_type == "article"
    && sanity::partOfRelease($releaseId)
  ] {
    "slug": slug.current,
    "sectionSlug": primarySection->slug.current,
    _id,
    title
  }
`;
/**
 * Find ALL documents versioned within a content release — no `_type` filter.
 *
 * The type-agnostic sibling of ARTICLES_IN_RELEASE_QUERY. A release full of
 * `openApiReference` (or any non-article) version docs expands to zero under
 * the article-gated query; this one expands it to every member document.
 *
 * Like ARTICLES_IN_RELEASE_QUERY it must be called with a perspective-enabled
 * client so versioned content is visible, and the perspective client resolves
 * versioned docs back to their canonical (published-form) `_id` rather than the
 * `versions.*`-prefixed id.
 *
 * Returns the document/version-key fields (`_id`, `_type`, `_rev`) plus the
 * editorial `slug` for display (null for typeless docs) and the parent
 * `sectionSlug` (`primarySection->slug.current`, null when absent — typeless
 * docs and docs without a section). `_rev` is the diff signal the release-diff
 * slice keys on; `sectionSlug` feeds the perspective-pin relatedness guard. The
 * release-diff path ignores `sectionSlug`, so the extra projection is additive.
 *
 * @param $releaseId — the release ID (e.g., "ailf-scenario-01-test")
 */
export const DOCS_IN_RELEASE_QUERY = `
  *[sanity::partOfRelease($releaseId)] {
    _id,
    _type,
    _rev,
    "slug": slug.current,
    "sectionSlug": primarySection->slug.current
  }
`;
