/**
 * Reference Solution: Custom Block Types in Portable Text
 *
 * Demonstrates:
 * - Defining custom block types with defineArrayMember
 * - Adding "code" and "callout" blocks to a PT field
 * - Rendering custom blocks with @portabletext/react
 * - TypeScript types for custom block shapes
 */

// === Part 1: Schema Definition (schemas/post.ts) ===

import {
  defineType,
  defineField,
  defineArrayMember,
} from "sanity"

export const postType = defineType({
  name: "post",
  title: "Post",
  type: "document",
  fields: [
    defineField({
      name: "title",
      title: "Title",
      type: "string",
    }),
    defineField({
      name: "body",
      title: "Body",
      type: "array",
      of: [
        // Standard block (paragraphs, headings, lists)
        defineArrayMember({
          type: "block",
          styles: [
            { title: "Normal", value: "normal" },
            { title: "H2", value: "h2" },
            { title: "H3", value: "h3" },
            { title: "Quote", value: "blockquote" },
          ],
          marks: {
            decorators: [
              { title: "Bold", value: "strong" },
              { title: "Italic", value: "em" },
              { title: "Code", value: "code" },
            ],
          },
        }),

        // Custom: Code block with language selection
        defineArrayMember({
          name: "code",
          title: "Code Block",
          type: "object",
          fields: [
            defineField({
              name: "language",
              title: "Language",
              type: "string",
              options: {
                list: [
                  { title: "JavaScript", value: "javascript" },
                  { title: "TypeScript", value: "typescript" },
                  { title: "HTML", value: "html" },
                  { title: "CSS", value: "css" },
                  { title: "Shell", value: "bash" },
                  { title: "JSON", value: "json" },
                ],
              },
            }),
            defineField({
              name: "code",
              title: "Code",
              type: "text",
              rows: 10,
            }),
            defineField({
              name: "filename",
              title: "Filename",
              type: "string",
            }),
          ],
          preview: {
            select: { language: "language", code: "code" },
            prepare({ language, code }) {
              return {
                title: `Code: ${language || "plain"}`,
                subtitle: code ? code.slice(0, 50) + "…" : "",
              }
            },
          },
        }),

        // Custom: Callout block with tone
        defineArrayMember({
          name: "callout",
          title: "Callout",
          type: "object",
          fields: [
            defineField({
              name: "tone",
              title: "Tone",
              type: "string",
              options: {
                list: [
                  { title: "Info", value: "info" },
                  { title: "Warning", value: "warning" },
                  { title: "Error", value: "error" },
                  { title: "Tip", value: "tip" },
                ],
                layout: "radio",
              },
              initialValue: "info",
            }),
            defineField({
              name: "text",
              title: "Text",
              type: "text",
              rows: 3,
            }),
          ],
          preview: {
            select: { tone: "tone", text: "text" },
            prepare({ tone, text }) {
              const icons = { info: "ℹ️", warning: "⚠️", error: "🚨", tip: "💡" }
              return {
                title: `${icons[tone as keyof typeof icons] || ""} ${tone || "info"} callout`,
                subtitle: text,
              }
            },
          },
        }),
      ],
    }),
  ],
})

// === Part 2: Frontend Rendering (components/PortableTextBody.tsx) ===

// import { PortableText, type PortableTextComponents } from "@portabletext/react"

interface CodeBlockValue {
  _type: "code"
  language?: string
  code: string
  filename?: string
}

interface CalloutBlockValue {
  _type: "callout"
  tone: "info" | "warning" | "error" | "tip"
  text: string
}

function CodeBlock({ value }: { value: CodeBlockValue }) {
  return (
    <figure>
      {value.filename && (
        <figcaption>{value.filename}</figcaption>
      )}
      <pre data-language={value.language}>
        <code>{value.code}</code>
      </pre>
    </figure>
  )
}

const toneStyles: Record<string, { background: string; border: string }> = {
  info: { background: "#e8f4fd", border: "#2196f3" },
  warning: { background: "#fff8e1", border: "#ff9800" },
  error: { background: "#fde8e8", border: "#f44336" },
  tip: { background: "#e8f5e9", border: "#4caf50" },
}

function CalloutBlock({ value }: { value: CalloutBlockValue }) {
  const style = toneStyles[value.tone] || toneStyles.info

  return (
    <aside
      role="note"
      style={{
        padding: "1rem",
        borderLeft: `4px solid ${style.border}`,
        background: style.background,
        margin: "1.5rem 0",
      }}
    >
      <p>{value.text}</p>
    </aside>
  )
}

// Register custom types in the PortableText component map
export const components = {
  types: {
    code: CodeBlock,
    callout: CalloutBlock,
  },
}

// Usage:
// <PortableText value={post.body} components={components} />
