import { useEffect, useState } from 'react'
import { useRouter } from 'next/router'
import { Select } from './form'
import { EXTRA_LONG_POLL_INTERVAL, SSR } from '@/lib/constants'
import { SUBS } from '@/fragments/subs'
import { useQuery } from '@apollo/client'
import styles from './sub-select.module.css'
import { useMe } from './me'

export function SubSelectInitial ({ sub }) {
  const router = useRouter()
  sub = sub || router.query.sub || 'pick territory'

  return {
    sub
  }
}

const DEFAULT_PREPEND_SUBS = []
const DEFAULT_APPEND_SUBS = []
const DEFAULT_FILTER_SUBS = () => true

export function useSubs ({ prependSubs = DEFAULT_PREPEND_SUBS, sub, filterSubs = DEFAULT_FILTER_SUBS, appendSubs = DEFAULT_APPEND_SUBS }) {
  const { data, refetch } = useQuery(SUBS, SSR
    ? {}
    : {
        pollInterval: EXTRA_LONG_POLL_INTERVAL,
        nextFetchPolicy: 'cache-and-network'
      })

  const { me } = useMe()

  useEffect(() => {
    refetch()
  }, [me?.privates?.nsfwMode])

  const [subs, setSubs] = useState([
    ...prependSubs.filter(s => s !== sub),
    ...(sub ? [sub] : []),
    ...appendSubs.filter(s => s !== sub)])

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

    const joined = data.subs.filter(filterSubs).filter(s => !s.meMuteSub).map(s => s.name)
    const muted = data.subs.filter(filterSubs).filter(s => s.meMuteSub).map(s => s.name)
    const mutedSection = muted.length ? [{ label: 'muted', items: muted }] : []
    setSubs([
      ...prependSubs,
      ...joined,
      ...mutedSection,
      ...appendSubs])
  }, [data])

  return subs
}

export default function SubSelect ({ prependSubs, sub, onChange, size, appendSubs, filterSubs, className, ...props }) {
  const router = useRouter()
  const subs = useSubs({ prependSubs, sub, filterSubs, appendSubs })
  const valueProps = props.noForm
    ? {
        value: sub
      }
    : {
        overrideValue: sub
      }

  // If logged out user directly visits a nsfw sub, subs will not contain `sub`, so manually add it
  // to display the correct sub name in the sub selector
  const subItems = !sub || subs.find((s) => s === sub) ? subs : [sub].concat(subs)

  return (
    <Select
      onChange={onChange || ((_, e) => {
        const sub = ['home', 'pick territory'].includes(e.target.value) ? undefined : e.target.value
        if (sub === 'create') {
          router.push('/territory')
          return
        }

        let asPath
        // are we currently in a sub (ie not home)
        if (router.query.sub) {
          // are we going to a sub or home?
          const subReplace = sub ? `/~${sub}` : ''

          // if we are going to a sub, replace the current sub with the new one
          asPath = router.asPath.replace(`/~${router.query.sub}`, subReplace)
          // if we're going to home, just go there directly
          if (asPath === '') {
            router.push('/')
            return
          }
        } else {
          // we're currently on the home sub
          // are we in a sub aware route?
          if (router.pathname.startsWith('/~')) {
            // if we are, go to the same path but in the sub
            asPath = `/~${sub}` + router.asPath
          } else {
            // otherwise, just go to the sub
            router.push(sub ? `/~${sub}` : '/')
            return
          }
        }
        const query = {
          ...router.query,
          sub
        }
        delete query.nodata
        router.push({
          pathname: router.pathname,
          query
        }, asPath)
      })}
      name='sub'
      size='sm'
      {...valueProps}
      {...props}
      className={`${className} ${styles.subSelect} ${size === 'large' ? styles.subSelectLarge : size === 'medium' ? styles.subSelectMedium : ''}`}
      items={subItems}
    />
  )
}