import { useQuery } from '@tanstack/react-query'
import { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
import { Helmet } from 'react-helmet-async'
import { useLocation, useNavigate } from 'react-router-dom'

import PostList from '@/components/PostList'
import PrefetchLink from '@/components/PrefetchLink'
import TagSidebar from '@/components/TagSidebar'
import WikiBody from '@/components/WikiBody'
import Pagination from '@/components/common/Pagination'
import TabGroup, { Tab } from '@/components/common/TabGroup'
import MainArea from '@/components/layout/MainArea'
import { SITE_TITLE } from '@/config'
import { fetchPosts } from '@/lib/posts'
import { postsKeys } from '@/lib/queryKeys'
import {
    DEFAULT_POST_LIST_LIMIT,
    getClientListLimit,
    LIST_LIMIT_OPTIONS,
    setClientListSettings,
} from '@/lib/settings'
import { useKeyboardShortcuts } from '@/lib/useKeyboardShortcuts'
import { fetchWikiPageByTitle } from '@/lib/wiki'

import type { FC } from 'react'

import type { WikiPage } from '@/types'

const parseLimit = (value: string | null): 20 | 50 | 100 | null => {
  const n = Number (value)
  return n === 20 || n === 50 || n === 100 ? n : null
}


const PostListPage: FC = () => {
  const containerRef = useRef<HTMLDivElement | null> (null)

  const [wikiPage, setWikiPage] = useState<WikiPage | null> (null)

  const location = useLocation ()
  const navigate = useNavigate ()
  const query = new URLSearchParams (location.search)
  const tagsQuery = query.get ('tags') ?? ''
  const anyFlg = query.get ('match') === 'any'
  const match = anyFlg ? 'any' : 'all'
  const tags = useMemo (() => tagsQuery.split (' ').filter (e => e !== ''), [tagsQuery])
  const tagsKey = tags.join (' ')
  const page = Number (query.get ('page') ?? 1)
  const limit = (
      parseLimit (query.get ('limit'))
      ?? getClientListLimit ('postList')
      ?? DEFAULT_POST_LIST_LIMIT
  )
  const order = 'original_created_at:desc' as const

  const keys = {
      tags: tagsKey, match, page, limit,
      url: '', title: '', originalCreatedFrom: '', originalCreatedTo: '',
      createdFrom: '', createdTo: '', updatedFrom: '', updatedTo: '',
      order } as const
  const { data, isLoading: loading } = useQuery ({
      queryKey: postsKeys.index (keys),
      queryFn:  () => fetchPosts (keys) })
  const posts = data?.posts ?? []
  const cursor = ''
  const totalPages = data ? Math.ceil (data.count / limit) : 0

  useEffect (() => {
    setClientListSettings ('postList', { limit })
  }, [limit])

  const updatePage = (nextPage: number) => {
    const params = new URLSearchParams (location.search)
    params.set ('page', String (Math.max (1, nextPage)))
    navigate (`${ location.pathname }?${ params.toString () }`)
  }

  const updateListQuery = (next: { limit?: 20 | 50 | 100 }) => {
    const params = new URLSearchParams (location.search)
    params.set ('limit', String (next.limit ?? limit))
    params.set ('page', '1')
    navigate (`${ location.pathname }?${ params.toString () }`)
  }

  useKeyboardShortcuts (useMemo (() => ({
      ...(page > 1
	  ? {
	      'pagination.previous': () => {
		  updatePage (page - 1)
	      },
	  }
	  : { }),
      ...(totalPages > 0 && page < totalPages
	  ? {
	      'pagination.next': () => {
		  updatePage (Math.min (page + 1, totalPages))
	      },
	  }
	  : { }),
  }), [page, totalPages, location.search]))

  useLayoutEffect (() => {
    scroll (0, 0)

    setWikiPage (null)

    if (tags.length !== 1)
      return

    void (async () => {
      try
      {
	const tagName = tags[0]
	setWikiPage (await fetchWikiPageByTitle (tagName, { }))
      }
      catch
      {
	;
      }
    }) ()
  }, [location.search, tags])

  return (
      <div
	  data-sidebar-container
	  className="md:flex md:flex-1 overflow-y-auto md:overflow-y-hidden"
	  ref={containerRef}>
	<Helmet>
	  <title>
	    {tags.length
	     ? `${ tags.join (anyFlg ? ' or ' : ' and ') } | ${ SITE_TITLE }`
	     : `${ SITE_TITLE }\u3000〜 ぼざろクリーチャーシリーズ綜合リンク集サイト`}
	  </title>
	</Helmet>

	<TagSidebar posts={posts.slice (0, 20)} onClick={() => {
	    const statesToSave = {
		posts, cursor,
		scroll: containerRef.current?.scrollTop ?? 0 }
	    sessionStorage.setItem (`posts:${ tagsQuery }`,
				    JSON.stringify (statesToSave))
	}}/>

	<MainArea>
	  <TabGroup
	      rightAddon={
		  <label className="flex items-center gap-2 text-xs text-muted-foreground">
		    <span>件数</span>
		    <select
			className="rounded border border-border bg-background px-2 py-1 text-sm
				   text-foreground"
			value={limit}
			onChange={ev => updateListQuery ({
			    limit: Number (ev.target.value) as 20 | 50 | 100,
			})}>
		      {LIST_LIMIT_OPTIONS.map (value => (
			  <option key={value} value={value}>
			    {value}
			  </option>))}
		    </select>
		  </label>
	      }>
	    <Tab name="広場">
	      {posts.length > 0
	       ? (
		  <>
		    <PostList posts={posts}/>
		    <Pagination page={page} totalPages={totalPages}/>
		  </>)
	       : !(loading) && '広場には何もありませんよ．'}
	      {loading && 'Loading...'}
	    </Tab>
	    {tags.length === 1 && (
		<Tab name="Wiki">
		  <WikiBody title={tags[0]} body={wikiPage?.body}/>
		  <div className="my-2">
		    <PrefetchLink to={`/wiki/${ encodeURIComponent (tags[0]) }`}>
		      Wiki を見る
		    </PrefetchLink>
		  </div>
		</Tab>)}
	  </TabGroup>
	</MainArea>
      </div>)
}

export default PostListPage
