import axios from 'axios'
import toCamel from 'camelcase-keys'
import { useEffect, useState } from 'react'
import { Helmet } from 'react-helmet-async'
import { useParams } from 'react-router-dom'

import TagDetailSidebar from '@/components/TagDetailSidebar'
import NicoViewer from '@/components/NicoViewer'
import PostEditForm from '@/components/PostEditForm'
import TabGroup, { Tab } from '@/components/common/TabGroup'
import MainArea from '@/components/layout/MainArea'
import { Button } from '@/components/ui/button'
import { toast } from '@/components/ui/use-toast'
import { API_BASE_URL, SITE_TITLE } from '@/config'
import { cn } from '@/lib/utils'
import NotFound from '@/pages/NotFound'
import ServiceUnavailable from '@/pages/ServiceUnavailable'

import type { Post, User } from '@/types'

type Props = { user: User | null }


export default ({ user }: Props) => {
  const { id } = useParams ()

  const [editing, setEditing] = useState (true)
  const [post, setPost] = useState<Post | null> (null)
  const [status, setStatus] = useState (200)

  const changeViewedFlg = async () => {
    const url = `${ API_BASE_URL }/posts/${ id }/viewed`
    const opt = { headers: { 'X-Transfer-Code': localStorage.getItem ('user_code') || '' } }
    try
    {
      if (post!.viewed)
	await axios.delete (url, opt)
      else
	await axios.post (url, { }, opt)

      // 通信に成功したら “閲覧済” をトグル
      setPost (post => ({ ...post!, viewed: !(post!.viewed) }))
    }
    catch
    {
      toast ({ title: '失敗……', description: '通信に失敗しました……' })
    }
  }

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

    const fetchPost = async () => {
      try
      {
	const res = await axios.get (`${ API_BASE_URL }/posts/${ id }`, { headers: {
	    'X-Transfer-Code': localStorage.getItem ('user_code') ?? '' } })
	setPost (toCamel (res.data as any, { deep: true }) as Post)
      }
      catch (err)
      {
	if (axios.isAxiosError (err))
	  setStatus (err.status ?? 200)
      }
    }
    fetchPost ()
  }, [id])

  useEffect (() => {
    setEditing (false)
  }, [post])

  useEffect (() => {
    if (!(editing))
      setEditing (true)
  }, [editing])

  switch (status)
  {
  case 404:
    return <NotFound />
  case 503:
    return <ServiceUnavailable />
  }

  const url = post ? new URL (post.url) : null
  const nicoFlg = url?.hostname.split ('.').slice (-2).join ('.') === 'nicovideo.jp'
  const match = nicoFlg ? url.pathname.match (/(?<=\/watch\/)[a-zA-Z0-9]+?(?=\/|$)/) : null
  const videoId = match?.[0] ?? ''
  const viewedClass = (post?.viewed
		       ? 'bg-blue-600 hover:bg-blue-700'
		       : 'bg-gray-500 hover:bg-gray-600')

  return (
      <div className="md:flex md:flex-1">
	<Helmet>
	  {(post?.thumbnail || post?.thumbnailBase) && (
	      <meta name="thumbnail" content={post.thumbnail || post.thumbnailBase} />)}
	  {post && <title>{`${ post.title || post.url } | ${ SITE_TITLE }`}</title>}
	</Helmet>
	<div className="hidden md:block">
	  <TagDetailSidebar post={post} />
	</div>
	<MainArea>
	  {post
	   ? (
	      <>
		{nicoFlg
		 ? (
		    <NicoViewer id={videoId}
				width={640}
				height={360} />)
		 : <img src={post.thumbnail} alt={post.url} className="mb-4 w-full" />}
		<Button onClick={changeViewedFlg}
			className={cn ('text-white', viewedClass)}>
		  {post.viewed ? '閲覧済' : '未閲覧'}
		</Button>
		<TabGroup>
		  {(['admin', 'member'].some (r => user?.role === r) && editing) && (
		      <Tab name="編輯">
			<PostEditForm post={post}
				      onSave={newPost => {
					setPost (newPost)
					toast ({ description: '更新しました．' })
				      }} />
		      </Tab>)}
		</TabGroup>
	      </>)
	   : 'Loading...'}
	</MainArea>
	<div className="md:hidden">
	  <TagDetailSidebar post={post} />
	</div>
      </div>)
}
