import type { ReactNode } from 'react'
import { useEffect, useState } from 'react'
import jwt from 'jsonwebtoken'
import { mdiForwardburger, mdiBackburger, mdiMenu } from '@mdi/js'
import menuAside from '../menuAside'
import menuNavBar from '../menuNavBar'
import BaseIcon from '../components/BaseIcon'
import NavBar from '../components/NavBar'
import NavBarItemPlain from '../components/NavBarItemPlain'
import AsideMenu from '../components/AsideMenu'
import FooterBar from '../components/FooterBar'
import MobileBottomNav from '../components/MobileBottomNav'
import { useAppDispatch, useAppSelector } from '../stores/hooks'
import Search from '../components/Search'
import { useRouter } from 'next/router'
import { findMe, logoutUser } from '../stores/authSlice'
import { humanize } from '../helpers/humanize'
import { hasPermission } from '../helpers/userPermissions'

type Props = {
  children: ReactNode
  permission?: string
}

function getMobilePageTitle(pathname: string) {
  const knownRoutes = [
    { prefix: '/dashboard', title: 'Home' },
    { prefix: '/daily-pulse', title: 'Daily Pulse' },
    { prefix: '/onboarding', title: 'Onboarding' },
    { prefix: '/goals', title: 'Goals' },
    { prefix: '/health_metrics', title: 'Vitals' },
    { prefix: '/conditions', title: 'Care' },
    { prefix: '/hydration_logs', title: 'Hydration' },
    { prefix: '/mood_logs', title: 'Mood' },
    { prefix: '/sleep_logs', title: 'Sleep' },
    { prefix: '/profile', title: 'Profile' },
  ]

  const matchedRoute = knownRoutes.find((route) => pathname.startsWith(route.prefix))

  if (matchedRoute) {
    return matchedRoute.title
  }

  const [firstSegment] = pathname.split('/').filter(Boolean)

  if (!firstSegment) {
    return 'Home'
  }

  return humanize(firstSegment.replace(/-/g, ' ').replace(/_/g, ' '))
}

export default function LayoutAuthenticated({ children, permission }: Props) {
  const dispatch = useAppDispatch()
  const router = useRouter()
  const { token, currentUser } = useAppSelector((state) => state.auth)
  const bgColor = useAppSelector((state) => state.style.bgLayoutColor)
  const darkMode = useAppSelector((state) => state.style.darkMode)
  const [isAsideMobileExpanded, setIsAsideMobileExpanded] = useState(false)
  const [isAsideLgActive, setIsAsideLgActive] = useState(false)

  let localToken
  if (typeof window !== 'undefined') {
    localToken = localStorage.getItem('token')
  }

  const isTokenValid = () => {
    const tokenValue = localStorage.getItem('token')

    if (!tokenValue) return

    const date = new Date().getTime() / 1000
    const data = jwt.decode(tokenValue)

    if (!data) return

    return date < data.exp
  }

  useEffect(() => {
    dispatch(findMe())
    if (!isTokenValid()) {
      dispatch(logoutUser())
      router.push('/login')
    }
  }, [token, localToken])

  useEffect(() => {
    if (!permission || !currentUser) return

    if (!hasPermission(currentUser, permission)) router.push('/error')
  }, [currentUser, permission])

  useEffect(() => {
    const handleRouteChangeStart = () => {
      setIsAsideMobileExpanded(false)
      setIsAsideLgActive(false)
    }

    router.events.on('routeChangeStart', handleRouteChangeStart)

    return () => {
      router.events.off('routeChangeStart', handleRouteChangeStart)
    }
  }, [router.events, dispatch])

  const layoutAsidePadding = 'xl:pl-60'
  const mobilePageTitle = getMobilePageTitle(router.pathname)

  return (
    <div className={`${darkMode ? 'dark' : ''} overflow-hidden lg:overflow-visible`}>
      <div
        className={`${layoutAsidePadding} ${
          isAsideMobileExpanded ? 'ml-60 lg:ml-0' : ''
        } pt-14 pb-24 min-h-screen w-screen transition-position lg:w-auto lg:pb-0 ${bgColor} dark:bg-dark-800 dark:text-slate-100`}
      >
        <NavBar
          menu={menuNavBar}
          className={`${layoutAsidePadding} ${isAsideMobileExpanded ? 'ml-60 lg:ml-0' : ''}`}
        >
          <NavBarItemPlain
            display="flex lg:hidden"
            onClick={() => setIsAsideMobileExpanded(!isAsideMobileExpanded)}
          >
            <BaseIcon path={isAsideMobileExpanded ? mdiBackburger : mdiForwardburger} size="24" />
          </NavBarItemPlain>
          <div className="flex min-w-0 flex-1 items-center px-1 lg:hidden">
            <div className="min-w-0">
              <div className="truncate text-[10px] font-semibold uppercase tracking-[0.28em] text-[#8A7C66] dark:text-slate-400">
                APEX BRAIN
              </div>
              <div className="truncate text-sm font-semibold text-[#1C1C1C] dark:text-white">
                {mobilePageTitle}
              </div>
            </div>
          </div>
          <NavBarItemPlain
            display="hidden lg:flex xl:hidden"
            onClick={() => setIsAsideLgActive(true)}
          >
            <BaseIcon path={mdiMenu} size="24" />
          </NavBarItemPlain>
          <NavBarItemPlain display="hidden lg:flex" useMargin>
            <Search />
          </NavBarItemPlain>
        </NavBar>
        <AsideMenu
          isAsideMobileExpanded={isAsideMobileExpanded}
          isAsideLgActive={isAsideLgActive}
          menu={menuAside}
          onAsideLgClose={() => setIsAsideLgActive(false)}
        />
        {children}
        <div className="hidden lg:block">
          <FooterBar>Hand-crafted & Made with ❤️</FooterBar>
        </div>
        <MobileBottomNav
          isMenuOpen={isAsideMobileExpanded}
          onMenuClick={() => setIsAsideMobileExpanded((currentValue) => !currentValue)}
        />
      </div>
    </div>
  )
}
