import axios from 'axios'
import toCamel from 'camelcase-keys'
import { Fragment, useState, useEffect } from 'react'
import { Link, useLocation } from 'react-router-dom'

import Separator from '@/components/MenuSeparator'
import TopNavUser from '@/components/TopNavUser'
import { API_BASE_URL } from '@/config'
import { WikiIdBus } from '@/lib/eventBus/WikiIdBus'
import { cn } from '@/lib/utils'

import type { FC } from 'react'

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

type Props = { user: User | null }


export default (({ user }: Props) => {
  const location = useLocation ()

  const [menuOpen, setMenuOpen] = useState (false)
  const [openItemIdx, setOpenItemIdx] = useState (-1)
  const [postCount, setPostCount] = useState<number | null> (null)
  const [wikiId, setWikiId] = useState<number | null> (WikiIdBus.get ())

  const wikiPageFlg = Boolean (/^\/wiki\/(?!new|changes)[^\/]+/.test (location.pathname) && wikiId)
  const wikiTitle = location.pathname.split ('/')[2]
  const menu: Menu = [
      { name: '広場', to: '/posts', subMenu: [
	  { name: '一覧', to: '/posts' },
	  { name: '投稿追加', to: '/posts/new' },
	  { name: '耕作履歴', to: '/posts/changes' },
	  { name: 'ヘルプ', to: '/wiki/ヘルプ:広場' }] },
      { name: 'タグ', to: '/tags', subMenu: [
	  { name: 'タグ一覧', to: '/tags', visible: false },
	  { name: '別名タグ', to: '/tags/aliases', visible: false },
	  { name: '上位タグ', to: '/tags/implications', visible: false },
	  { name: 'ニコニコ連携', to: '/tags/nico' },
	  { name: 'ヘルプ', to: '/wiki/ヘルプ:タグ' }] },
      { name: 'Wiki', to: '/wiki/ヘルプ:ホーム', base: '/wiki', subMenu: [
	  { name: '検索', to: '/wiki' },
	  { name: '新規', to: '/wiki/new' },
	  { name: '全体履歴', to: '/wiki/changes' },
	  { name: 'ヘルプ', to: '/wiki/ヘルプ:Wiki' },
	  { component: <Separator/>, visible: wikiPageFlg },
	  { name: `広場 (${ postCount || 0 })`, to: `/posts?tags=${ wikiTitle }`,
	    visible: wikiPageFlg },
	  { name: '履歴', to: `/wiki/changes?id=${ wikiId }`, visible: wikiPageFlg },
	  { name: '編輯', to: `/wiki/${ wikiId || wikiTitle }/edit`, visible: wikiPageFlg }] },
      { name: 'ユーザ', to: '/users', subMenu: [
	  { name: '一覧', to: '/users', visible: false },
	  { name: 'お前', to: `/users/${ user?.id }`, visible: false },
	  { name: '設定', to: '/users/settings', visible: Boolean (user) }] }]

  useEffect (() => {
    const unsubscribe = WikiIdBus.subscribe (setWikiId)
    return () => unsubscribe ()
  }, [])

  useEffect (() => {
    setMenuOpen (false)
    setOpenItemIdx (menu.findIndex (item => (
	location.pathname.startsWith (item.base || item.to))))
  }, [location])

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

    const fetchPostCount = async () => {
      try
      {
	const pageRes = await axios.get (`${ API_BASE_URL }/wiki/${ wikiId }`)
	const wikiPage = toCamel (pageRes.data as any, { deep: true }) as WikiPage

	const tagRes = await axios.get (`${ API_BASE_URL }/tags/name/${ wikiPage.title }`)
	const tag = toCamel (tagRes.data as any, { deep: true }) as Tag

	setPostCount (tag.postCount)
      }
      catch
      {
	setPostCount (0)
      }
    }
    fetchPostCount ()
  }, [wikiId])

  return (
      <>
	<nav className="px-3 flex justify-between items-center w-full min-h-[48px]
			bg-yellow-200 dark:bg-red-975 md:bg-yellow-50">
	  <div className="flex items-center gap-2 h-full">
	    <Link to="/"
		  className="mx-4 text-xl font-bold text-pink-600 hover:text-pink-400
			     dark:text-pink-300 dark:hover:text-pink-100">
	      ぼざクリ タグ広場
	    </Link>

	    {menu.map ((item, i) => (
		<Link key={i}
		      to={item.to}
		      className={cn ('hidden md:flex h-full items-center',
				     (location.pathname.startsWith (item.base || item.to)
				      ? 'bg-yellow-200 dark:bg-red-950 px-4 font-bold'
				      : 'px-2'))}>
		  {item.name}
		</Link>
	    ))}
	  </div>

	  <TopNavUser user={user}/>

	  <a href="#"
	     className="md:hidden ml-auto pr-4
			text-pink-600 hover:text-pink-400
			dark:text-pink-300 dark:hover:text-pink-100"
	     onClick={ev => {
	       ev.preventDefault ()
	       setMenuOpen (!(menuOpen))
	     }}>
	    {menuOpen ? '×' : 'Menu'}
	  </a>
	</nav>

	<div className="hidden md:flex bg-yellow-200 dark:bg-red-950
			items-center w-full min-h-[40px] px-3">
	  {menu.find (item => location.pathname.startsWith (item.base || item.to))?.subMenu
	   .filter (item => item.visible ?? true)
	   .map ((item, i) => 'component' in item ? item.component : (
	      <Link key={i}
		    to={item.to}
		    className="h-full flex items-center px-3">
		{item.name}
	      </Link>))}
	</div>

	<div className={cn (menuOpen ? 'flex flex-col md:hidden' : 'hidden',
			    'bg-yellow-200 dark:bg-red-975 items-start')}>
	  <Separator/>
	  {menu.map ((item, i) => (
	      <Fragment key={i}>
		<Link to={i === openItemIdx ? item.to : '#'}
		      className={cn ('w-full min-h-[40px] flex items-center pl-8',
				     ((i === openItemIdx)
				      && 'font-bold bg-yellow-50 dark:bg-red-950'))}
		      onClick={ev => {
			if (i !== openItemIdx)
			  {
			    ev.preventDefault ()
			    setOpenItemIdx (i)
			  }
		      }}>
		  {item.name}
		</Link>
		{i === openItemIdx && (
		    item.subMenu
		    .filter (subItem => subItem.visible ?? true)
		    .map ((subItem, j) => 'component' in subItem ? subItem.component : (
			<Link key={j}
			      to={subItem.to}
			      className="w-full min-h-[36px] flex items-center pl-12
					 bg-yellow-50 dark:bg-red-950">
			  {subItem.name}
			</Link>)))}
	      </Fragment>))}
	  <TopNavUser user={user} sp/>
	  <Separator/>
	</div>
      </>)
}) satisfies FC<Props>
