import { AnimatePresence, LayoutGroup } from 'framer-motion'
import { useEffect, useState } from 'react'
import { BrowserRouter,
	 Navigate,
	 Route,
	 Routes,
	 useLocation } from 'react-router-dom'

import RouteBlockerOverlay from '@/components/RouteBlockerOverlay'
import TopNav from '@/components/TopNav'
import { Toaster } from '@/components/ui/toaster'
import { apiPost, isApiError } from '@/lib/api'
import NicoTagListPage from '@/pages/tags/NicoTagListPage'
import NotFound from '@/pages/NotFound'
import PostDetailPage from '@/pages/posts/PostDetailPage'
import PostHistoryPage from '@/pages/posts/PostHistoryPage'
import PostListPage from '@/pages/posts/PostListPage'
import PostNewPage from '@/pages/posts/PostNewPage'
import ServiceUnavailable from '@/pages/ServiceUnavailable'
import SettingPage from '@/pages/users/SettingPage'
import WikiDetailPage from '@/pages/wiki/WikiDetailPage'
import WikiDiffPage from '@/pages/wiki/WikiDiffPage'
import WikiEditPage from '@/pages/wiki/WikiEditPage'
import WikiHistoryPage from '@/pages/wiki/WikiHistoryPage'
import WikiNewPage from '@/pages/wiki/WikiNewPage'
import WikiSearchPage from '@/pages/wiki/WikiSearchPage'

import type { Dispatch, FC, SetStateAction } from 'react'

import type { User } from '@/types'


const RouteTransitionWrapper = ({ user, setUser }: {
    user:     User | null
    setUser:  Dispatch<SetStateAction<User | null>> }) => {
  const location = useLocation ()

  return (
      <LayoutGroup id="gallery-shared">
	<AnimatePresence mode="wait">
	  <Routes location={location} key={location.pathname}>
	    <Route path="/" element={<Navigate to="/posts" replace/>}/>
	    <Route path="/posts" element={<PostListPage/>}/>
	    <Route path="/posts/new" element={<PostNewPage user={user}/>}/>
	    <Route path="/posts/:id" element={<PostDetailRoute user={user}/>}/>
	    <Route path="/posts/changes" element={<PostHistoryPage/>}/>
	    <Route path="/tags/nico" element={<NicoTagListPage user={user}/>}/>
	    <Route path="/wiki" element={<WikiSearchPage/>}/>
	    <Route path="/wiki/:title" element={<WikiDetailPage/>}/>
	    <Route path="/wiki/new" element={<WikiNewPage user={user}/>}/>
	    <Route path="/wiki/:id/edit" element={<WikiEditPage user={user}/>}/>
	    <Route path="/wiki/:id/diff" element={<WikiDiffPage/>}/>
	    <Route path="/wiki/changes" element={<WikiHistoryPage/>}/>
	    <Route path="/users/settings" element={<SettingPage user={user} setUser={setUser}/>}/>
	    <Route path="/settings" element={<Navigate to="/users/settings" replace/>}/>
	    <Route path="*" element={<NotFound/>}/>
	  </Routes>
	</AnimatePresence>
      </LayoutGroup>)
}


const PostDetailRoute = ({ user }: { user: User | null }) => {
  const location = useLocation ()
  const key = location.pathname
  return <PostDetailPage key={key} user={user}/>
}


export default (() => {
  const [user, setUser] = useState<User | null> (null)
  const [status, setStatus] = useState (200)

  useEffect (() => {
    const createUser = async () => {
      const data = await apiPost<{ code: string; user: User }> ('/users')
      if (data.code)
	{
	  localStorage.setItem ('user_code', data.code)
	  setUser (data.user)
	}
    }

    const code = localStorage.getItem ('user_code')
    if (code)
      {
	void (async () => {
	  try
	  {
	    const data = await apiPost<{ valid: boolean; user: User }> ('/users/verify', { code })
	    if (data.valid)
	      setUser (data.user)
	    else
	      await createUser ()
	  }
	  catch (err)
	  {
	    if (isApiError (err))
	      setStatus (err.response?.status ?? 200)
	  }
	}) ()
      }
    else
      createUser ()
  }, [])

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

  return (
      <>
	<RouteBlockerOverlay/>
	<BrowserRouter>
	  <div className="flex flex-col h-screen w-screen">
	    <TopNav user={user}/>
	    <RouteTransitionWrapper user={user} setUser={setUser}/>
	  </div>
	  <Toaster/>
	</BrowserRouter>
      </>)
}) satisfies FC
