/**
 * Reference Solution: Image Asset Pipeline with Responsive Images
 *
 * Demonstrates:
 * - Setting up @sanity/image-url builder
 * - Hotspot and crop support
 * - Responsive srcSet generation for multiple widths
 * - WebP format with auto-format
 * - Reusable React component with TypeScript props
 */

import imageUrlBuilder from "@sanity/image-url"
import { createClient } from "@sanity/client"

// === Client & Image Builder Setup ===

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

const builder = imageUrlBuilder(client)

// === Types ===

interface SanityImageCrop {
  top: number
  bottom: number
  left: number
  right: number
}

interface SanityImageHotspot {
  x: number
  y: number
  height: number
  width: number
}

interface SanityImageSource {
  _type: "image"
  asset: {
    _ref: string
    _type: "reference"
  }
  crop?: SanityImageCrop
  hotspot?: SanityImageHotspot
  alt?: string
}

interface SanityImageProps {
  /** The image field value from a Sanity document */
  image: SanityImageSource
  /** Alt text override (falls back to image.alt) */
  alt?: string
  /** Max display width in pixels */
  maxWidth?: number
  /** CSS sizes attribute for responsive images */
  sizes?: string
  /** Additional CSS class names */
  className?: string
  /** Loading strategy */
  loading?: "lazy" | "eager"
  /** Priority hint for LCP images */
  priority?: boolean
}

// === Image URL Helper ===

/**
 * Generate a URL for a Sanity image with transforms applied.
 * The builder automatically respects hotspot and crop metadata.
 */
function urlFor(source: SanityImageSource) {
  return builder.image(source)
}

// === Responsive Breakpoints ===

const DEFAULT_WIDTHS = [320, 480, 640, 768, 1024, 1280, 1536, 1920]
const DEFAULT_MAX_WIDTH = 1920
const DEFAULT_SIZES = "(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"

// === Generate srcSet ===

function generateSrcSet(
  image: SanityImageSource,
  widths: number[] = DEFAULT_WIDTHS,
): string {
  return widths
    .map((w) => {
      const url = urlFor(image)
        .width(w)
        .auto("format") // Serves WebP to browsers that support it
        .fit("crop") // Respects hotspot and crop data
        .url()

      return `${url} ${w}w`
    })
    .join(", ")
}

// === React Component ===

export function SanityImage({
  image,
  alt,
  maxWidth = DEFAULT_MAX_WIDTH,
  sizes = DEFAULT_SIZES,
  className,
  loading = "lazy",
  priority = false,
}: SanityImageProps) {
  if (!image?.asset) return null

  // Filter widths to only include those up to maxWidth
  const widths = DEFAULT_WIDTHS.filter((w) => w <= maxWidth)
  if (widths[widths.length - 1] !== maxWidth) {
    widths.push(maxWidth)
  }

  // Default src at maxWidth for non-srcset browsers
  const src = urlFor(image)
    .width(maxWidth)
    .auto("format")
    .fit("crop")
    .url()

  const srcSet = generateSrcSet(image, widths)

  return (
    <img
      src={src}
      srcSet={srcSet}
      sizes={sizes}
      alt={alt || image.alt || ""}
      className={className}
      loading={priority ? "eager" : loading}
      decoding={priority ? "sync" : "async"}
      style={{ maxWidth: "100%", height: "auto" }}
    />
  )
}

// === Low-Level Helpers (for non-React usage) ===

/**
 * Get a single image URL with transforms applied.
 *
 * @example
 * const url = getImageUrl(post.mainImage, { width: 800, height: 600 })
 */
export function getImageUrl(
  source: SanityImageSource,
  options: { width?: number; height?: number; quality?: number } = {},
): string {
  let img = urlFor(source).auto("format").fit("crop")

  if (options.width) img = img.width(options.width)
  if (options.height) img = img.height(options.height)
  if (options.quality) img = img.quality(options.quality)

  return img.url()
}
