import {
  createContext,
  CSSProperties,
  ReactNode,
  useCallback,
  useContext,
  useMemo,
  useState,
} from 'react'

const MediaPreviewsContext = createContext<{
  previews: { [key: string]: string }
  addPreview: (id: string, objectURL: string) => void
}>({ previews: {}, addPreview: () => {} })

type ImagePreviewsContextProviderProps = { children: ReactNode }

function MediaPreviewsContextProvider({
  children,
}: ImagePreviewsContextProviderProps) {
  const [previews, setPreviews] = useState({})

  const addPreview = useCallback((id: string, objectURL: string) => {
    setPreviews((p) => ({ ...p, [id]: objectURL }))
  }, [])

  return (
    <MediaPreviewsContext.Provider value={{ previews, addPreview }}>
      {children}
    </MediaPreviewsContext.Provider>
  )
}

function useMediaPreviews() {
  return useContext(MediaPreviewsContext)
}

function getOptimizedImageSrc(src: string, width: number) {
  if (
    !src ||
    !src.includes('.based.dev/') ||
    src.includes('cdn-cgi/image/') ||
    src.includes('.ico')
  )
    return src

  return src.replace('.based.dev/', `.based.dev/cdn-cgi/image/w=${width}/`)
}

type MediaProps = {
  data: any
  objectFit?: CSSProperties['objectFit']
  optimizedImageWidth?: number
}

function Media({
  data,
  objectFit = 'cover',
  optimizedImageWidth = 512,
}: MediaProps) {
  const { previews } = useMediaPreviews()

  const src = useMemo(
    () =>
      previews[data?.id ?? data?.src] ??
      getOptimizedImageSrc(data?.src, optimizedImageWidth),
    [data?.id, data?.src, optimizedImageWidth, previews],
  )

  return <img src={src} style={{ width: '100%', height: '100%', objectFit }} />
}

export type { MediaProps }
export { Media, MediaPreviewsContextProvider, useMediaPreviews }
