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

import TagLink from '@/components/TagLink'
import SectionTitle from '@/components/common/SectionTitle'
import TextArea from '@/components/common/TextArea'
import MainArea from '@/components/layout/MainArea'
import { toast } from '@/components/ui/use-toast'
import { API_BASE_URL, SITE_TITLE } from '@/config'

import type { NicoTag, Tag, User } from '@/types'

type Props = { user: User | null }


export default ({ user }: Props) => {
  const [cursor, setCursor] = useState ('')
  const [editing, setEditing] = useState<{ [key: number]: boolean }> ({ })
  const [loading, setLoading] = useState (false)
  const [nicoTags, setNicoTags] = useState<NicoTag[]> ([])
  const [rawTags, setRawTags] = useState<{ [key: number]: string }> ({ })

  const loaderRef = useRef<HTMLDivElement | null> (null)

  const memberFlg = ['admin', 'member'].some (r => user?.role === r)

  const loadMore = async (withCursor: boolean) => {
    setLoading (true)

    const res = await axios.get (`${ API_BASE_URL }/tags/nico`, {
	params: { ...(withCursor ? { cursor } : { }) } })
    const data = toCamel (res.data as any, { deep: true }) as { tags:       NicoTag[]
								nextCursor: string }

    setNicoTags (tags => [...(withCursor ? tags : []), ...data.tags])
    setCursor (data.nextCursor)

    const newEditing = Object.fromEntries (data.tags.map (t => [t.id, false]))
    setEditing (editing => ({ ...editing, ...newEditing }))

    const newRawTags = Object.fromEntries (
	data.tags.map (t => [t.id, t.linkedTags.map (lt => lt.name).join (' ')]))
    setRawTags (rawTags => ({ ...rawTags, ...newRawTags }))

    setLoading (false)
  }

  const handleEdit = async (id: number) => {
    if (editing[id])
      {
	const formData = new FormData
	formData.append ('tags', rawTags[id])

	const res = await axios.put (`${ API_BASE_URL }/tags/nico/${ id }`, formData, { headers: {
	    'Content-Type':     'multipart/form-data',
	    'X-Transfer-Code':  localStorage.getItem ('user_code') ?? '' } })
	const data = toCamel (res.data as any, { deep: true }) as Tag[]
	setNicoTags (nicoTags => {
	  nicoTags.find (t => t.id === id)!.linkedTags = data
	  return [...nicoTags]
	})
	setRawTags (rawTags => ({ ...rawTags, [id]: data.map (t => t.name).join (' ') }))

	toast ({ title: '更新しました．' })
      }

    setEditing (editing => ({ ...editing, [id]: !(editing[id]) }))
  }

  useEffect(() => {
    const observer = new IntersectionObserver (entries => {
      if (entries[0].isIntersecting && !(loading) && cursor)
	loadMore (true)
    }, { threshold: 1 })

    const target = loaderRef.current
    if (target)
      observer.observe (target)

    return () => {
      if (target)
	observer.unobserve (target)
    }
  }, [loaderRef, loading])

  useEffect (() => {
    setNicoTags ([])
    loadMore (false)
  }, [])

  return (
      <MainArea>
	<Helmet>
	  <title>ニコニコ連携 | {SITE_TITLE}</title>
	</Helmet>

	<div className="max-w-xl">
	  <SectionTitle>ニコニコ連携</SectionTitle>
	</div>

	<div className="mt-4">
	  {nicoTags.length > 0 && (
	      <table className="table-auto w-full border-collapse mb-4">
		<thead>
		  <tr>
		    <th className="p-2 text-left">ニコニコタグ</th>
		    <th className="p-2 text-left">連携タグ</th>
		    {memberFlg && <th></th>}
		  </tr>
		</thead>
		<tbody>
		  {nicoTags.map ((tag, i) => (
		      <tr key={i}>
			<td className="p-2">
			  <TagLink tag={tag} withWiki={false} withCount={false}/>
			</td>
			<td className="p-2">
			  {editing[tag.id]
			   ? (
			      <TextArea value={rawTags[tag.id]} onChange={ev => {
				setRawTags (rawTags => ({ ...rawTags, [tag.id]: ev.target.value }))
			      }}/>)
			   : tag.linkedTags.map((lt, j) => (
			      <span key={j} className="mr-2">
				<TagLink tag={lt}
					 linkFlg={false}
					 withCount={false}/>
			      </span>))}
			</td>
			{memberFlg && (
			    <td>
			      <a href="#" onClick={ev => {
				ev.preventDefault ()
				handleEdit (tag.id)
			      }}>
			        {editing[tag.id]
				 ? (
				    <span className="text-red-600 hover:text-red-400
						     dark:text-red-300 dark:hover:text-red-100">
				      更新
				    </span>)
				 : <span>編輯</span>}
			      </a>
			    </td>)}
		      </tr>))}
		</tbody>
	      </table>)}
	  {loading && 'Loading...'}
	  <div ref={loaderRef} className="h-12"></div>
	</div>
      </MainArea>)
}
