import { AnimatePresence, motion } from 'framer-motion'
import { useEffect, useState } from 'react'
import { useLocation, useNavigate } from 'react-router-dom'

import TagLink from '@/components/TagLink'
import TagSearch from '@/components/TagSearch'
import SectionTitle from '@/components/common/SectionTitle'
import SidebarComponent from '@/components/layout/SidebarComponent'
import { CATEGORIES } from '@/consts'
import { apiGet } from '@/lib/api'

import type { FC, MouseEvent } from 'react'

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

type TagByCategory = Record<string, Tag[]>

type Props = { posts:     Post[]
	       onClick?:  (event: MouseEvent<HTMLElement>) => void }


export default (({ posts, onClick }: Props) => {
  const navigate = useNavigate ()

  const [tagsVsbl, setTagsVsbl] = useState (false)
  const [tags, setTags] = useState<TagByCategory> ({ })

  const location = useLocation ()
  const query = new URLSearchParams (location.search)
  const tagsQuery = query.get ('tags') ?? ''
  const anyFlg = query.get ('match') === 'any'

  useEffect (() => {
    const tagsTmp: TagByCategory = { }
    let cnt = 0

  loop:
    for (const post of posts)
      {
	for (const tag of post.tags)
	  {
	    if (!(tag.category in tagsTmp))
	      tagsTmp[tag.category] = []

	    if (!(tagsTmp[tag.category].map (t => t.id).includes (tag.id)))
	      {
		tagsTmp[tag.category].push (tag)
		++cnt
		if (cnt >= 25)
		  break loop
	      }
	  }
      }

    for (const cat of Object.keys (tagsTmp))
      tagsTmp[cat].sort ((tagA, tagB) => tagA.name < tagB.name ? -1 : 1)

    setTags (tagsTmp)
  }, [posts])

  const TagBlock = (
      <>
	<SectionTitle>タグ</SectionTitle>
	<ul>
	  {CATEGORIES.flatMap (cat => cat in tags ? (
	      tags[cat].map (tag => (
		  <li key={tag.id} className="mb-1">
		    <TagLink tag={tag} prefetch onClick={onClick}/>
		  </li>))) : [])}
	</ul>
	<SectionTitle>関聯</SectionTitle>
	{posts.length > 0 && (
	    <a href="#"
	       onClick={ev => {
		 ev.preventDefault ()
		 void ((async () => {
		   try
		   {
		     const data = await apiGet<Post> ('/posts/random',
			 { params: { tags: tagsQuery.split (' ').filter (e => e !== '').join (' '),
				     match: (anyFlg ? 'any' : 'all') } })
		     navigate (`/posts/${ data.id }`)
		   }
		   catch
		   {
		     ;
		   }
		 }) ())
	       }}>
	      ランダム
	    </a>)}
      </>)

  return (
      <SidebarComponent>
	<TagSearch/>

	<div className="hidden md:block mt-4">
	  {TagBlock}
	</div>

	<AnimatePresence initial={false}>
	  {tagsVsbl && (
	      <motion.div
		  key="sptags"
		  className="md:hidden mt-4"
		  variants={{ hidden:   { clipPath: 'inset(0 0 100% 0)',
					  height:   0 },
			      visible:  { clipPath: 'inset(0 0 0% 0)',
					  height:   'auto'} }}
		  initial="hidden"
		  animate="visible"
		  exit="hidden"
		  transition={{ duration: .2, ease: 'easeOut' }}>
		{TagBlock}
	      </motion.div>)}
	</AnimatePresence>

	<a href="#"
	   className="md:hidden block my-2 text-center text-sm
		      text-gray-500 hover:text-gray-400
		      dark:text-gray-300 dark:hover:text-gray-100"
	   onClick={ev => {
	     ev.preventDefault ()
	     setTagsVsbl (v => !(v))
	   }}>
	  {tagsVsbl ? '▲▲▲ タグ一覧を閉じる ▲▲▲' : '▼▼▼ タグ一覧を表示 ▼▼▼'}
	</a>
      </SidebarComponent>)
}) satisfies FC<Props>
