import {
  useEffect,
  useState,
  useCallback,
  ChangeEvent,
  ClipboardEvent,
  MouseEventHandler,
  FormEvent,
  useRef
} from "react"
import Image from 'next/image'
import PasteIcon from '@/assets/images/paste.svg'
import UploadIcon from '@/assets/images/upload.svg'
import CameraIcon from '@/assets/images/camera.svg'
import { useBing } from '@/lib/hooks/use-bing'
import { cn } from '@/lib/utils'

interface ChatImageProps extends Pick<ReturnType<typeof useBing>, 'uploadImage'> {}

const preventDefault: MouseEventHandler<HTMLDivElement> = (event) => {
  event.nativeEvent.stopImmediatePropagation()
}

const toBase64 = (file: File): Promise<string> => new Promise((resolve, reject) => {
  const reader = new FileReader()
  reader.readAsDataURL(file)
  reader.onload = () => resolve(reader.result as string)
  reader.onerror = reject
})

export function ChatImage({ children, uploadImage }: React.PropsWithChildren<ChatImageProps>) {
  const videoRef = useRef<HTMLVideoElement>(null)
  const canvasRef = useRef<HTMLCanvasElement>(null)
  const mediaStream = useRef<MediaStream>()
  const [panel, setPanel] = useState('none')

  const upload = useCallback((url: string) => {
    if (url) {
      uploadImage(url)
    }
    setPanel('none')
  }, [panel])

  const onUpload = useCallback(async (event: ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0]
    if (file) {
      const fileDataUrl = await toBase64(file)
      if (fileDataUrl) {
        upload(fileDataUrl)
      }
    }
  }, [])

  const onPaste = useCallback((event: ClipboardEvent<HTMLInputElement>) => {
    const pasteUrl = event.clipboardData.getData('text') ?? ''
    upload(pasteUrl)
  }, [])

  const onEnter = useCallback((event: FormEvent<HTMLFormElement>) => {
    event.preventDefault()
    event.stopPropagation()
    // @ts-ignore
    const inputUrl = event.target.elements.image.value
    if (inputUrl) {
      upload(inputUrl)
    }
  }, [])

  const openVideo: MouseEventHandler<HTMLButtonElement> = async (event) => {
    event.stopPropagation()
    setPanel('camera-mode')
  }

  const onCapture = () => {
    if (canvasRef.current && videoRef.current) {
      const canvas = canvasRef.current
      canvas.width = videoRef.current!.videoWidth
      canvas.height = videoRef.current!.videoHeight
      canvas.getContext('2d')?.drawImage(videoRef.current, 0, 0, canvas.width, canvas.height)
      const cameraUrl = canvas.toDataURL('image/jpeg')
      upload(cameraUrl)
    }
  }

  useEffect(() => {
    const handleBlur = () => {
      if (panel !== 'none') {
        setPanel('none')
      }
    }
    document.addEventListener('click', handleBlur)
    return () => {
      document.removeEventListener('click', handleBlur)
    }
  }, [panel])

  useEffect(() => {
    if (panel === 'camera-mode') {
      navigator.mediaDevices.getUserMedia({ video: true, audio: false })
      .then(videoStream => {
        mediaStream.current = videoStream
        if (videoRef.current) {
          videoRef.current.srcObject = videoStream
        }
      })
    } else {
      if (mediaStream.current) {
        mediaStream.current.getTracks().forEach(function(track) {
          track.stop()
        })
        mediaStream.current = undefined
      }
    }
  }, [panel])

  return (
    <div className="visual-search-container">
      <div onClick={() => panel === 'none' ? setPanel('normal') : setPanel('none')}>{children}</div>
      <div className={cn('visual-search', panel)} onClick={preventDefault}>
        <div className="normal-content">
          <div className="header">
            <h4>添加图像</h4>
          </div>
          <div className="paste">
            <Image alt="paste" src={PasteIcon} width={24} />
            <form onSubmitCapture={onEnter}>
              <input
                className="paste-input"
                id="sb_imgpst"
                type="text"
                name="image"
                placeholder="粘贴图像 URL"
                aria-label="粘贴图像 URL"
                onPaste={onPaste}
                onClickCapture={(e) => e.stopPropagation()}
              />
            </form>
          </div>
          <div className="buttons">
            <button type="button" aria-label="从此设备上传">
              <input
                id="vs_fileinput"
                className="fileinput"
                type="file"
                accept="image/gif, image/jpeg, image/png, image/webp"
                onChange={onUpload}
              />
              <Image alt="uplaod" src={UploadIcon} width={20} />
              从此设备上传
            </button>
            <button type="button" aria-label="拍照" onClick={openVideo}>
              <Image alt="camera" src={CameraIcon} width={20} />
              拍照
            </button>
          </div>
        </div>
        {panel === 'camera-mode' && <div className="cam-content">
          <div className="webvideo-container">
            <video className="webvideo" autoPlay muted playsInline ref={videoRef} />
            <canvas className="webcanvas" ref={canvasRef} />
          </div>
          <div className="cambtn" role="button" aria-label="拍照" onClick={onCapture}>
            <div className="cam-btn-circle-large"></div>
            <div className="cam-btn-circle-small"></div>
          </div>
        </div>}
      </div>
    </div>
  )
}