import React, { useMemo, forwardRef } from 'react'
import ReactPlayer from 'react-player'
import { classifyUrl } from '../utils/helpers'

interface VideoEmbedProcessorProps {
  html: string
  renderVideoLinksAsEmbeds: boolean
  className?: string
  onMouseUp?: (e: React.MouseEvent) => void
  onTouchEnd?: (e: React.TouchEvent) => void
}

/**
 * Component that processes HTML content and optionally embeds video links
 * as ReactPlayer components when renderVideoLinksAsEmbeds is enabled
 */
const VideoEmbedProcessor = forwardRef<HTMLDivElement, VideoEmbedProcessorProps>(({
  html,
  renderVideoLinksAsEmbeds,
  className,
  onMouseUp,
  onTouchEnd
}, ref) => {
  const processedHtml = useMemo(() => {
    if (!renderVideoLinksAsEmbeds || !html) {
      return html
    }

    // Process HTML in stages: <video> blocks, <img> tags with video src, and bare video URLs
    let result = html

    const collectedUrls: string[] = []
    let placeholderIndex = 0

    // 1) Replace entire <video>...</video> blocks when they reference a video URL
    const videoBlockPattern = /<video[^>]*>[\s\S]*?<\/video>/gi
    const videoBlocks = result.match(videoBlockPattern) || []
    videoBlocks.forEach((block) => {
      // Try src on <video>
      let url: string | null = null
      const videoSrcMatch = block.match(/<video[^>]*\s+src=["']?(https?:\/\/[^\s<>"']+\.(mp4|webm|ogg|mov|avi|mkv|m4v)[^\s<>"']*)["']?[^>]*>/i)
      if (videoSrcMatch && videoSrcMatch[1]) {
        url = videoSrcMatch[1]
      } else {
        // Try nested <source>
        const sourceSrcMatch = block.match(/<source[^>]*\s+src=["']?(https?:\/\/[^\s<>"']+\.(mp4|webm|ogg|mov|avi|mkv|m4v)[^\s<>"']*)["']?[^>]*>/i)
        if (sourceSrcMatch && sourceSrcMatch[1]) {
          url = sourceSrcMatch[1]
        }
      }
      if (url) {
        collectedUrls.push(url)
        const placeholder = `__VIDEO_EMBED_${placeholderIndex}__`
        const escaped = block.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
        result = result.replace(new RegExp(escaped, 'g'), placeholder)
        placeholderIndex++
      }
    })

    // 2) Replace entire <img ...> tags if their src points to a video
    const imgTagPattern = /<img[^>]*>/gi
    const allImgTags = result.match(imgTagPattern) || []
    allImgTags.forEach((imgTag) => {
      const srcMatch = imgTag.match(/src=["']?(https?:\/\/[^\s<>"']+\.(mp4|webm|ogg|mov|avi|mkv|m4v)[^\s<>"']*)["']?/i)
      if (srcMatch && srcMatch[1]) {
        const videoUrl = srcMatch[1]
        collectedUrls.push(videoUrl)
        const placeholder = `__VIDEO_EMBED_${placeholderIndex}__`
        const escapedTag = imgTag.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
        result = result.replace(new RegExp(escapedTag, 'g'), placeholder)
        placeholderIndex++
      }
    })

    // 3) Replace remaining bare video URLs (direct files or recognized video platforms)
    const fileVideoPattern = /https?:\/\/[^\s<>"']+\.(mp4|webm|ogg|mov|avi|mkv|m4v)(?:\?[^\s<>"']*)?/gi
    const fileVideoUrls: string[] = result.match(fileVideoPattern) || []

    const allUrlPattern = /https?:\/\/[^\s<>"']+(?=\s|>|"|'|$)/gi
    const allUrls: string[] = result.match(allUrlPattern) || []
    const platformVideoUrls = allUrls.filter(url => {
      // include URLs classified as video and not already collected
      const classification = classifyUrl(url)
      return classification.type === 'video' && !collectedUrls.includes(url)
    })

    const remainingUrls = [...fileVideoUrls, ...platformVideoUrls].filter(url => !collectedUrls.includes(url))

    let processedHtml = result
    remainingUrls.forEach((url) => {
      const placeholder = `__VIDEO_EMBED_${placeholderIndex}__`
      processedHtml = processedHtml.replace(new RegExp(url.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), placeholder)
      collectedUrls.push(url)
      placeholderIndex++
    })

    // If nothing collected, return original html
    if (collectedUrls.length === 0) {
      return html
    }

    return processedHtml
  }, [html, renderVideoLinksAsEmbeds])

  const videoUrls = useMemo(() => {
    if (!renderVideoLinksAsEmbeds || !html) {
      return []
    }

    const urls: string[] = []

    // 1) Extract from <video> blocks first (video src or nested source src)
    const videoBlockPattern = /<video[^>]*>[\s\S]*?<\/video>/gi
    const videoBlocks = html.match(videoBlockPattern) || []
    videoBlocks.forEach((block) => {
      let url: string | null = null
      const videoSrcMatch = block.match(/<video[^>]*\s+src=["']?(https?:\/\/[^\s<>"']+\.(mp4|webm|ogg|mov|avi|mkv|m4v)[^\s<>"']*)["']?[^>]*>/i)
      if (videoSrcMatch && videoSrcMatch[1]) {
        url = videoSrcMatch[1]
      } else {
        const sourceSrcMatch = block.match(/<source[^>]*\s+src=["']?(https?:\/\/[^\s<>"']+\.(mp4|webm|ogg|mov|avi|mkv|m4v)[^\s<>"']*)["']?[^>]*>/i)
        if (sourceSrcMatch && sourceSrcMatch[1]) {
          url = sourceSrcMatch[1]
        }
      }
      if (url && !urls.includes(url)) urls.push(url)
    })

    // 2) Extract from <img> tags with video src
    const imgTagPattern = /<img[^>]*>/gi
    const allImgTags = html.match(imgTagPattern) || []
    allImgTags.forEach((imgTag) => {
      const srcMatch = imgTag.match(/src=["']?(https?:\/\/[^\s<>"']+\.(mp4|webm|ogg|mov|avi|mkv|m4v)[^\s<>"']*)["']?/i)
      if (srcMatch && srcMatch[1] && !urls.includes(srcMatch[1])) {
        urls.push(srcMatch[1])
      }
    })

    // 3) Extract remaining direct file URLs and platform-classified video URLs
    const fileVideoPattern = /https?:\/\/[^\s<>"']+\.(mp4|webm|ogg|mov|avi|mkv|m4v)(?:\?[^\s<>"']*)?/gi
    const fileVideoUrls: string[] = html.match(fileVideoPattern) || []
    fileVideoUrls.forEach(u => { if (!urls.includes(u)) urls.push(u) })

    const allUrlPattern = /https?:\/\/[^\s<>"']+(?=\s|>|"|'|$)/gi
    const allUrls: string[] = html.match(allUrlPattern) || []
    allUrls.forEach(u => {
      const classification = classifyUrl(u)
      if (classification.type === 'video' && !urls.includes(u)) {
        urls.push(u)
      }
    })

    return urls
  }, [html, renderVideoLinksAsEmbeds])

  // If no video embedding is enabled, just render the HTML normally
  if (!renderVideoLinksAsEmbeds || videoUrls.length === 0) {
    return (
      <div 
        ref={ref}
        className={className}
        dangerouslySetInnerHTML={{ __html: processedHtml }}
        onMouseUp={onMouseUp}
        onTouchEnd={onTouchEnd}
      />
    )
  }

  // Split the HTML by video placeholders and render with embedded players
  const parts = processedHtml.split(/(__VIDEO_EMBED_\d+__)/)
  
  return (
    <div ref={ref} className={className} onMouseUp={onMouseUp} onTouchEnd={onTouchEnd}>
      {parts.map((part, index) => {
        const videoMatch = part.match(/^__VIDEO_EMBED_(\d+)__$/)
        if (videoMatch) {
          const videoIndex = parseInt(videoMatch[1])
          const videoUrl = videoUrls[videoIndex]
          if (videoUrl) {
            return (
              <div key={index} className="reader-video" style={{ margin: '1rem 0' }}>
                <ReactPlayer 
                  url={videoUrl}
                  controls 
                  width="100%"
                  height="auto"
                  style={{ 
                    width: '100%', 
                    height: 'auto', 
                    aspectRatio: '16/9' 
                  }}
                />
              </div>
            )
          }
        }
        
        // Regular HTML content
        return (
          <div 
            key={index}
            dangerouslySetInnerHTML={{ __html: part }}
          />
        )
      })}
    </div>
  )
})

VideoEmbedProcessor.displayName = 'VideoEmbedProcessor'

export default VideoEmbedProcessor
