import { useEffect, useRef, useState, type ImgHTMLAttributes } from "react"

/**
 * LazyImage — only loads the image when it enters the viewport.
 * Uses IntersectionObserver with a configurable root margin so
 * images load slightly before they scroll into view.
 */
export interface LazyImageProps extends ImgHTMLAttributes<HTMLImageElement> {
  /** How far outside the viewport to begin loading (default "200px") */
  rootMargin?: string
}

export default function LazyImage({ rootMargin = "200px", style, alt, ...rest }: LazyImageProps) {
  const ref = useRef<HTMLImageElement | null>(null)
  const [visible, setVisible] = useState(false)
  const [loaded, setLoaded] = useState(false)

  useEffect(() => {
    const node = ref.current
    if (!node) return
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          setVisible(true)
          observer.disconnect()
        }
      },
      { rootMargin },
    )
    observer.observe(node)
    return () => observer.disconnect()
  }, [rootMargin])

  const inline: React.CSSProperties = {
    display: "block",
    maxWidth: "100%",
    height: "auto",
    objectFit: "contain",
    borderRadius: 6,
    minHeight: visible && !loaded ? 120 : undefined,
    opacity: loaded ? 1 : 0,
    transition: "opacity 0.25s ease",
    background: !loaded ? "#f5f5f5" : undefined,
    ...style,
  }

  return (
    <img
      ref={ref}
      {...rest}
      alt={alt || "附件图片"}
      loading="lazy"
      decoding="async"
      src={visible ? rest.src : undefined}
      style={inline}
      onLoad={() => setLoaded(true)}
    />
  )
}

/**
 * Build a thumbnail URL from a media URL path.
 * For /media/ticket-images/2026/06/15/112228_abc.png this returns
 * /api/v1/tickets/attachments/images/thumbnail?path=ticket-images/2026/06/15/112228_abc.png
 *
 * @param src - The original image src URL
 * @param admin - If true, uses the admin endpoint
 */
function mediaUrlToThumbnailUrl(src: string, admin = false): string | null {
  const tokenMatch = /\/attachments\/images\/file\/([A-Za-z0-9_-]+)/.exec(src)
  if (tokenMatch) {
    const apiBase = import.meta.env.VITE_API_BASE_URL || "/api"
    const prefix = admin ? `${apiBase}/v1/admin/tickets` : `${apiBase}/v1/tickets`
    return `${prefix}/attachments/images/thumbnail/${encodeURIComponent(tokenMatch[1])}`
  }

  // Extract the relative media path from various URL forms
  let mediaPath: string
  const mediaIdx = src.indexOf("/media/")
  if (mediaIdx >= 0) {
    mediaPath = src.substring(mediaIdx + 7) // skip "/media/"
  } else {
    // Already relative, check if it's a ticket image
    if (src.startsWith("ticket-images/")) {
      mediaPath = src
    } else {
      return null
    }
  }
  mediaPath = mediaPath.replace(/^\/+/, "")
  if (!mediaPath.startsWith("ticket-images/")) return null

  // Determine API base
  const apiBase = import.meta.env.VITE_API_BASE_URL || "/api"
  const prefix = admin ? `${apiBase}/v1/admin/tickets` : `${apiBase}/v1/tickets`
  return `${prefix}/attachments/images/thumbnail?path=${encodeURIComponent(mediaPath)}`
}

/**
 * Process an HTML string, replacing image src attributes with thumbnail URLs
 * for inline display while preserving the original URL as data-original-src.
 * Also adds lazy loading and async decoding attributes.
 *
 * The first 2 images across ALL calls get eager loading + high fetchpriority.
 * Subsequent images use lazy loading for bandwidth efficiency.
 *
 * @param html - The sanitized HTML string
 * @param admin - If true, thumbnails are served via the admin API endpoint
 * @param globalImgOffset - Application-level image counter (pass from caller)
 */
export function injectLazyImageMarkers(html: string, admin = false): string {
  if (!html.includes("<img")) return html

  let imgIndex = 0

  return html.replace(
    /<img\b([^>]*)>/gi,
    (_match: string, attrs: string) => {
      let result = attrs
      const isFirstImages = imgIndex < 2
      imgIndex++

      // Extract current src
      const srcMatch = /\bsrc="([^"]*)"/i.exec(result)
      const originalSrc = srcMatch ? srcMatch[1] : null

      // Add data-original-src for preview
      if (originalSrc && !/\bdata-original-src\s*=/i.test(result)) {
        result += ` data-original-src="${originalSrc}"`
      }

      // Replace src with thumbnail for inline display (save bandwidth)
      if (originalSrc) {
        const thumb = mediaUrlToThumbnailUrl(originalSrc, admin)
        if (thumb) {
          result = result.replace(/\bsrc="[^"]*"/i, `src="${thumb}"`)
        }
      }

      if (!/\bloading\s*=/i.test(result)) {
        result += ' loading="lazy"'
      }
      if (!/\bdecoding\s*=/i.test(result)) {
        result += ' decoding="async"'
      }

      // First 2 images get eager loading to appear immediately
      if (isFirstImages && /\bloading="lazy"/i.test(result)) {
        result = result.replace(/\bloading="lazy"/i, 'loading="eager"')
      }
      if (isFirstImages && !/\bfetchpriority\s*=/i.test(result)) {
        result += ' fetchpriority="high"'
      }

      return `<img${result} />`
    },
  )
}
