/**
 * Reference Solution: Portable Text Rendering in React
 *
 * Demonstrates:
 * - Setting up @portabletext/react with custom components
 * - Handling image blocks with @sanity/image-url
 * - Custom marks for links (internal + external)
 * - Code block rendering with language metadata
 * - TypeScript types for component props
 */

import { PortableText, type PortableTextComponents } from "@portabletext/react"
import imageUrlBuilder from "@sanity/image-url"
import { createClient } from "@sanity/client"

// === Sanity Client & Image Builder ===

const client = createClient({
  projectId: "your-project-id",
  dataset: "production",
  apiVersion: "2024-01-01",
  useCdn: true,
})

const builder = imageUrlBuilder(client)

function urlFor(source: SanityImageSource) {
  return builder.image(source)
}

// === Types ===

interface SanityImageSource {
  _type: "image"
  asset: {
    _ref: string
    _type: "reference"
  }
  hotspot?: { x: number; y: number; height: number; width: number }
  crop?: { top: number; bottom: number; left: number; right: number }
}

interface ImageBlockValue {
  _type: "image"
  asset: { _ref: string; _type: "reference" }
  hotspot?: SanityImageSource["hotspot"]
  crop?: SanityImageSource["crop"]
  alt?: string
  caption?: string
}

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

interface LinkMarkValue {
  _type: "link"
  href: string
  blank?: boolean
}

interface InternalLinkMarkValue {
  _type: "internalLink"
  reference: { _ref: string; _type: "reference" }
  slug?: { current: string }
}

interface PortableTextBodyProps {
  value: unknown[]
  className?: string
}

// === Custom Components ===

// Image block — renders Sanity images with hotspot/crop via the URL builder
function ImageBlock({ value }: { value: ImageBlockValue }) {
  if (!value?.asset) return null

  const url = urlFor(value)
    .width(800)
    .auto("format")
    .url()

  return (
    <figure>
      <img
        src={url}
        alt={value.alt || ""}
        loading="lazy"
        style={{ maxWidth: "100%", height: "auto" }}
      />
      {value.caption && <figcaption>{value.caption}</figcaption>}
    </figure>
  )
}

// Code block — renders preformatted code with language annotation
function CodeBlock({ value }: { value: CodeBlockValue }) {
  return (
    <pre data-language={value.language}>
      <code>{value.code}</code>
    </pre>
  )
}

// External link mark — opens in new tab when blank is true
function LinkMark({
  value,
  children,
}: {
  value?: LinkMarkValue
  children: React.ReactNode
}) {
  const target = value?.blank ? "_blank" : undefined
  const rel = value?.blank ? "noopener noreferrer" : undefined

  return (
    <a href={value?.href} target={target} rel={rel}>
      {children}
    </a>
  )
}

// Internal link mark — resolves to a local route
function InternalLinkMark({
  value,
  children,
}: {
  value?: InternalLinkMarkValue
  children: React.ReactNode
}) {
  const slug = value?.slug?.current
  const href = slug ? `/${slug}` : "#"

  return <a href={href}>{children}</a>
}

// === Component Map ===

const components: PortableTextComponents = {
  types: {
    image: ImageBlock,
    code: CodeBlock,
  },
  marks: {
    link: LinkMark,
    internalLink: InternalLinkMark,
  },
}

// === Main Component ===

export function PortableTextBody({ value, className }: PortableTextBodyProps) {
  if (!value) return null

  return (
    <div className={className}>
      <PortableText value={value} components={components} />
    </div>
  )
}
