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

import PostFormTagsArea from '@/components/PostFormTagsArea'
import PostOriginalCreatedTimeField from '@/components/PostOriginalCreatedTimeField'
import Form from '@/components/common/Form'
import Label from '@/components/common/Label'
import PageTitle from '@/components/common/PageTitle'
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 Forbidden from '@/pages/Forbidden'

import type { FC } from 'react'

import type { User } from '@/types'

type Props = { user: User | null }


export default (({ user }: Props) => {
  if (!(['admin', 'member'].some (r => user?.role === r)))
    return <Forbidden/>

  const navigate = useNavigate ()

  const [originalCreatedBefore, setOriginalCreatedBefore] = useState<string | null> (null)
  const [originalCreatedFrom, setOriginalCreatedFrom] = useState<string | null> (null)
  const [tags, setTags] = useState ('')
  const [thumbnailAutoFlg, setThumbnailAutoFlg] = useState (true)
  const [thumbnailFile, setThumbnailFile] = useState<File | null> (null)
  const [thumbnailLoading, setThumbnailLoading] = useState (false)
  const [thumbnailPreview, setThumbnailPreview] = useState<string> ('')
  const [title, setTitle] = useState ('')
  const [titleAutoFlg, setTitleAutoFlg] = useState (true)
  const [titleLoading, setTitleLoading] = useState (false)
  const [url, setURL] = useState ('')

  const previousURLRef = useRef ('')

  const handleSubmit = async () => {
    const formData = new FormData
    formData.append ('title', title)
    formData.append ('url', url)
    formData.append ('tags', tags)
    if (thumbnailFile)
      formData.append ('thumbnail', thumbnailFile)
    if (originalCreatedFrom)
      formData.append ('original_created_from', originalCreatedFrom)
    if (originalCreatedBefore)
      formData.append ('original_created_before', originalCreatedBefore)

    try
    {
      await axios.post (`${ API_BASE_URL }/posts`, formData, { headers: {
	  'Content-Type':     'multipart/form-data',
	  'X-Transfer-Code':  localStorage.getItem ('user_code') ?? '' } })
      toast ({ title: '投稿成功!' })
      navigate ('/posts')
    }
    catch
    {
      toast ({ title: '投稿失敗', description: '入力を確認してください。' })
    }
  }

  useEffect (() => {
    if (titleAutoFlg && url)
      fetchTitle ()
  }, [titleAutoFlg])

  useEffect (() => {
    if (thumbnailAutoFlg && url)
      fetchThumbnail ()
  }, [thumbnailAutoFlg])

  const handleURLBlur = () => {
    if (!(url) || url === previousURLRef.current)
      return

    if (titleAutoFlg)
      fetchTitle ()
    if (thumbnailAutoFlg)
      fetchThumbnail ()
    previousURLRef.current = url
  }

  const fetchTitle = async () => {
    setTitle ('')
    setTitleLoading (true)
    const res = await axios.get (`${ API_BASE_URL }/preview/title`, {
	params:   { url },
	headers:  { 'X-Transfer-Code': localStorage.getItem ('user_code') || '' } })
    const data = res.data as { title: string }
    setTitle (data.title || '')
    setTitleLoading (false)
  }

  const fetchThumbnail = async () => {
    setThumbnailPreview ('')
    setThumbnailFile (null)
    setThumbnailLoading (true)
    if (thumbnailPreview)
      URL.revokeObjectURL (thumbnailPreview)
    const res = await axios.get (`${ API_BASE_URL }/preview/thumbnail`, {
	params:       { url },
	headers:      { 'X-Transfer-Code': localStorage.getItem ('user_code') || '' },
	responseType: 'blob' })
    const data = res.data as Blob
    const imageURL = URL.createObjectURL (data)
    setThumbnailPreview (imageURL)
    setThumbnailFile (new File ([data],
				'thumbnail.png',
				{ type: data.type || 'image/png' }))
    setThumbnailLoading (false)
  }

  return (
      <MainArea>
	<Helmet>
	  <title>{`広場に投稿を追加 | ${ SITE_TITLE }`}</title>
	</Helmet>
	<Form>
	  <PageTitle>広場に投稿を追加する</PageTitle>

	  {/* URL */}
	  <div>
	    <Label>URL</Label>
	    <input type="url"
		   placeholder="例：https://www.nicovideo.jp/watch/..."
		   value={url}
		   onChange={e => setURL (e.target.value)}
		   className="w-full border p-2 rounded"
		   onBlur={handleURLBlur}/>
	  </div>

	  {/* タイトル */}
	  <div>
	    <Label checkBox={{
		label:    '自動',
		checked:  titleAutoFlg,
		onChange: ev => setTitleAutoFlg (ev.target.checked)}}>
	      タイトル
	    </Label>
	    <input type="text"
		   className="w-full border rounded p-2"
		   value={title}
		   placeholder={titleLoading ? 'Loading...' : ''}
		   onChange={ev => setTitle (ev.target.value)}
		   disabled={titleAutoFlg}/>
	  </div>

	  {/* サムネール */}
	  <div>
	    <Label checkBox={{
		label:    '自動',
		checked:  thumbnailAutoFlg,
		onChange: ev => setThumbnailAutoFlg (ev.target.checked)}}>
	      サムネール
	    </Label>
	    {thumbnailAutoFlg
	     ? (thumbnailLoading
		? <p className="text-gray-500 text-sm">Loading...</p>
		: !(thumbnailPreview) && (
		    <p className="text-gray-500 text-sm">
		      URL から自動取得されます。
		    </p>))
	     : (
		<input type="file"
		       accept="image/*"
		       onChange={e => {
			 const file = e.target.files?.[0]
			 if (file)
			   {
			     setThumbnailFile (file)
			     setThumbnailPreview (URL.createObjectURL (file))
			   }
		       }}/>)}
	    {thumbnailPreview && (
		<img src={thumbnailPreview}
		     alt="preview"
		     className="mt-2 max-h-48 rounded border"/>)}
	  </div>

	  {/* タグ */}
	  <PostFormTagsArea tags={tags} setTags={setTags}/>

	  {/* オリジナルの作成日時 */}
	  <PostOriginalCreatedTimeField
	      originalCreatedFrom={originalCreatedFrom}
	      setOriginalCreatedFrom={setOriginalCreatedFrom}
	      originalCreatedBefore={originalCreatedBefore}
	      setOriginalCreatedBefore={setOriginalCreatedBefore}/>

	  {/* 送信 */}
	  <Button onClick={handleSubmit}
		  className="px-4 py-2 bg-blue-600 text-white rounded disabled:bg-gray-400"
		  disabled={titleLoading || thumbnailLoading}>
	    追加
	  </Button>
	</Form>
      </MainArea>)
}) satisfies FC<Props>
