/**
 * Reference Solution: Content Lake CRUD Operations
 *
 * Demonstrates:
 * - Creating documents with client.create()
 * - Patching documents with set, unset, inc
 * - Deleting documents with client.delete()
 * - Atomic transactions for multiple mutations
 * - TypeScript types for document shapes
 */

import { createClient, type SanityDocument } from "@sanity/client"

// === Client Setup ===

const client = createClient({
  projectId: "your-project-id",
  dataset: "production",
  apiVersion: "2024-01-01",
  token: process.env.SANITY_API_TOKEN,
  useCdn: false, // Mutations require the write API, not CDN
})

// === Types ===

interface Post {
  _type: "post"
  title: string
  slug: { _type: "slug"; current: string }
  publishedAt: string
  viewCount: number
  author: { _type: "reference"; _ref: string }
  categories?: Array<{ _type: "reference"; _ref: string }>
}

type PostDocument = SanityDocument & Post

// === 1. Create a Document ===

export async function createPost(data: {
  title: string
  slug: string
  authorId: string
}): Promise<PostDocument> {
  return client.create<Post>({
    _type: "post",
    title: data.title,
    slug: { _type: "slug", current: data.slug },
    publishedAt: new Date().toISOString(),
    viewCount: 0,
    author: { _type: "reference", _ref: data.authorId },
  })
}

// === 2. Patch a Document ===

// Set and unset fields
export async function updatePostTitle(
  postId: string,
  title: string,
): Promise<PostDocument> {
  return client
    .patch(postId)
    .set({ title })
    .unset(["subtitle"]) // Remove a field
    .commit<PostDocument>()
}

// Increment a numeric field
export async function incrementViewCount(
  postId: string,
): Promise<PostDocument> {
  return client
    .patch(postId)
    .inc({ viewCount: 1 })
    .commit<PostDocument>()
}

// Insert into an array
export async function addCategory(
  postId: string,
  categoryId: string,
): Promise<PostDocument> {
  return client
    .patch(postId)
    .setIfMissing({ categories: [] })
    .insert("after", "categories[-1]", [
      { _type: "reference", _ref: categoryId },
    ])
    .commit<PostDocument>()
}

// === 3. Delete a Document ===

export async function deletePost(postId: string): Promise<void> {
  await client.delete(postId)
}

// Delete with a GROQ filter
export async function deleteDraftPosts(): Promise<void> {
  // Delete all drafts of posts (draft IDs start with "drafts.")
  await client.delete({
    query: '*[_type == "post" && _id in path("drafts.**")]',
  })
}

// === 4. Transactions (Atomic Multi-Mutation) ===

export async function publishPostWithCategories(data: {
  title: string
  slug: string
  authorId: string
  categoryNames: string[]
}): Promise<void> {
  const transaction = client.transaction()

  // Create category documents
  const categoryIds: string[] = []
  for (const name of data.categoryNames) {
    const id = `category-${name.toLowerCase().replace(/\s+/g, "-")}`
    categoryIds.push(id)

    transaction.createIfNotExists({
      _id: id,
      _type: "category",
      title: name,
    })
  }

  // Create the post with references to categories
  transaction.create({
    _type: "post",
    title: data.title,
    slug: { _type: "slug", current: data.slug },
    publishedAt: new Date().toISOString(),
    viewCount: 0,
    author: { _type: "reference", _ref: data.authorId },
    categories: categoryIds.map((id) => ({
      _type: "reference",
      _ref: id,
    })),
  })

  // All mutations happen atomically
  await transaction.commit()
}

// === 5. createOrReplace — Idempotent upsert ===

export async function upsertSettings(settings: {
  siteName: string
  description: string
}): Promise<SanityDocument> {
  return client.createOrReplace({
    _id: "siteSettings",
    _type: "siteSettings",
    siteName: settings.siteName,
    description: settings.description,
  })
}
