"use client"

import { useEffect } from "react"
import { getAssetFallback } from "@/lib/asset-fallbacks"

const S3_HOST = "mgmindia.s3.ap-south-1.amazonaws.com"
const SIZE_PREFIXES = ["large_", "medium_", "small_", "thumbnail_"]
const EXTENSIONS = ["jpg", "jpeg", "png", "webp", "gif", "svg"]

function pushCandidate(candidates: string[], sourceUrl: URL, pathname: string) {
  const nextUrl = new URL(sourceUrl.href)
  nextUrl.pathname = pathname
  if (!candidates.includes(nextUrl.href)) candidates.push(nextUrl.href)
}

function addDuplicateExtensionCandidates(candidates: string[], url: URL) {
  const decodedPath = decodeURIComponent(url.pathname)

  for (const ext of EXTENSIONS) {
    const pattern = new RegExp(`\\.${ext} \\(\\d+\\)\\.(?:${EXTENSIONS.join("|")})$`, "i")
    if (!pattern.test(decodedPath)) continue

    pushCandidate(candidates, url, encodeURI(decodedPath.replace(pattern, `.${ext}`)))
  }
}

function buildVariantCandidates(src: string): string[] {
  try {
    const url = new URL(src, window.location.origin)
    const candidates: string[] = []

    const assetFallback = getAssetFallback(decodeURIComponent(url.pathname))
    if (assetFallback) candidates.push(assetFallback)

    if (url.hostname === S3_HOST && url.pathname.startsWith("/assets/")) {
      addDuplicateExtensionCandidates(candidates, url)
    }

    if (url.hostname === S3_HOST && url.pathname.startsWith("/uploads/")) {
      const parts = url.pathname.split("/")
      const fileName = parts.pop() || ""
      const currentPrefix = SIZE_PREFIXES.find((prefix) => fileName.startsWith(prefix))
      const baseName = currentPrefix ? fileName.slice(currentPrefix.length) : fileName

      for (const prefix of SIZE_PREFIXES) {
        const nextName = `${prefix}${baseName}`
        if (nextName !== fileName) {
          pushCandidate(candidates, url, [...parts, nextName].join("/"))
        }
      }

      if (currentPrefix) {
        pushCandidate(candidates, url, [...parts, baseName].join("/"))
      }
    }

    if (url.hostname === "localhost" || url.hostname === "127.0.0.1") {
      candidates.push(url.pathname + url.search)
    }

    return candidates
  } catch {
    return []
  }
}

type FallbackElement = HTMLImageElement | HTMLVideoElement

function elementSrc(element: FallbackElement): string {
  return element instanceof HTMLImageElement
    ? element.currentSrc || element.src
    : element.currentSrc || element.src
}

function nextFallback(element: FallbackElement): string | null {
  const explicitFallback = element.dataset.fallbackSrc
  if (explicitFallback && elementSrc(element) !== explicitFallback) {
    return explicitFallback
  }

  const tried = new Set((element.dataset.fallbackTried || "").split("|").filter(Boolean))
  for (const candidate of buildVariantCandidates(elementSrc(element))) {
    if (!tried.has(candidate)) {
      tried.add(candidate)
      element.dataset.fallbackTried = Array.from(tried).join("|")
      return candidate
    }
  }

  return null
}

export default function GlobalImageFallback() {
  useEffect(() => {
    const onImageError = (event: Event) => {
      const target = event.target
      if (!(target instanceof HTMLImageElement) && !(target instanceof HTMLVideoElement)) return
      if (target.dataset.fallbackFinal === "true") return

      const fallback = nextFallback(target)
      if (!fallback) {
        target.dataset.fallbackFinal = "true"
        target.hidden = true
        return
      }

      target.src = fallback
      if (target instanceof HTMLVideoElement) target.load()
    }

    document.addEventListener("error", onImageError, true)
    return () => document.removeEventListener("error", onImageError, true)
  }, [])

  return null
}
