import { useEffect, useRef, useState } from 'react'
import { Helmet } from 'react-helmet-async'
import { useParams } from 'react-router-dom'

import PostEmbed from '@/components/PostEmbed'
import MainArea from '@/components/layout/MainArea'
import { SITE_TITLE } from '@/config'
import { apiGet, apiPatch, apiPut } from '@/lib/api'
import { fetchPost } from '@/lib/posts'

import type { FC } from 'react'

import type { NiconicoMetadata, NiconicoViewerHandle, Post, Theatre } from '@/types'

type TheatreInfo = {
    hostFlg:        boolean
    postId:         number | null
    postStartedAt:  string | null }


export default (() => {
  const { id } = useParams ()

  const embedRef = useRef<NiconicoViewerHandle> (null)

  const [loading, setLoading] = useState (false)
  const [theatre, setTheatre] = useState<Theatre | null> (null)
  const [theatreInfo, setTheatreInfo] =
      useState<TheatreInfo> ({ hostFlg: false, postId: null, postStartedAt: null })
  const [post, setPost] = useState<Post | null> (null)
  const [videoLength, setVideoLength] = useState (9_999_999_999)

  useEffect (() => {
    if (!(id))
      return

    void (async () => {
      setTheatre (await apiGet<Theatre> (`/theatres/${ id }`))
    }) ()

    const interval = setInterval (async () => {
      if (theatreInfo.hostFlg
	  && theatreInfo.postStartedAt
	  && ((new Date).getTime () - (new Date (theatreInfo.postStartedAt)).getTime ()
	      > videoLength))
	setTheatreInfo ({ hostFlg: true, postId: null, postStartedAt: null })
      else
	setTheatreInfo (await apiPut<TheatreInfo> (`/theatres/${ id }/watching`))
    }, 1_000)

    return () => clearInterval (interval)
  }, [id, theatreInfo.hostFlg, theatreInfo.postStartedAt, videoLength])

  useEffect (() => {
    if (!(theatreInfo.hostFlg) || loading)
      return

    if (theatreInfo.postId == null)
      {
	void (async () => {
	  setLoading (true)
	  await apiPatch<void> (`/theatres/${ id }/next_post`)
	  setLoading (false)
	}) ()
	return
      }
  }, [id, loading, theatreInfo.hostFlg, theatreInfo.postId])

  useEffect (() => {
    if (theatreInfo.postId == null)
      return

    void (async () => {
      setPost (await fetchPost (String (theatreInfo.postId)))
    }) ()
  }, [theatreInfo.postId, theatreInfo.postStartedAt])

  const syncPlayback = (meta: NiconicoMetadata) => {
    if (!(theatreInfo.postStartedAt))
      return

    const targetTime =
	((new Date).getTime () - (new Date (theatreInfo.postStartedAt)).getTime ())

    const drift = Math.abs (meta.currentTime - targetTime)

    if (drift > 5_000)
      embedRef.current?.seek (targetTime)
  }

  return (
      <MainArea>
	<Helmet>
	  {theatre && (
	      <title>
		{'上映会場'
		 + (theatre.name ? `『${ theatre.name }』` : ` #${ theatre.id }`)
		 + ` | ${ SITE_TITLE }`}
	      </title>)}
	</Helmet>

	{post && (
	    <PostEmbed
		ref={embedRef}
		post={post}
		onLoadComplete={info => {
		  embedRef.current?.play ()
		  setVideoLength (info.lengthInSeconds * 1_000)
		}}
		onMetadataChange={meta => {
		  syncPlayback (meta)
		}}/>)}
      </MainArea>)
}) satisfies FC
