import React, { ReactNode, useEffect, useRef, useState } from 'react'
import jwt from 'jsonwebtoken';
import axios from 'axios';
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 { useAppDispatch, useAppSelector } from '../stores/hooks'
import Search from '../components/Search';
import { useRouter } from 'next/router'
import {findMe, logoutUser} from "../stores/authSlice";

import {hasPermission} from "../helpers/userPermissions";


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

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 meRequestedRef = useRef<string | null>(null);

  const getStoredToken = () => {
    if (typeof window === 'undefined') return null;
    return sessionStorage.getItem('token') || localStorage.getItem('token');
  };

  const isTokenValid = (tokenToCheck?: string | null) => {
    if (!tokenToCheck) return false;

    try {
      const decoded = jwt.decode(tokenToCheck);
      if (!decoded || typeof decoded !== 'object') return false;
      if (typeof decoded.exp !== 'number') return true;
      return Date.now() / 1000 < decoded.exp;
    } catch (error) {
      console.error('Failed to decode auth token:', error);
      return false;
    }
  };

  useEffect(() => {
    if (!router.isReady) return;

    const storedToken = getStoredToken();
    const authToken = token || storedToken;

    if (!authToken || !isTokenValid(authToken)) {
      dispatch(logoutUser());
      if (router.pathname !== '/login') {
        router.replace('/login');
      }
      return;
    }

    axios.defaults.headers.common.Authorization = `Bearer ${authToken}`;

    if (!currentUser && meRequestedRef.current !== authToken) {
      meRequestedRef.current = authToken;
      dispatch(findMe());
    }
  }, [router.isReady, router.pathname, token, currentUser, dispatch]);

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

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

  const darkMode = useAppSelector((state) => state.style.darkMode)
  const isConstructorFullscreen = router.pathname === '/constructor'

  const [isAsideMobileExpanded, setIsAsideMobileExpanded] = useState(false)
  const [isAsideLgActive, setIsAsideLgActive] = useState(false)

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

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

    // If the component is unmounted, unsubscribe
    // from the event with the `off` method:
    return () => {
      router.events.off('routeChangeStart', handleRouteChangeStart)
    }
  }, [router.events, dispatch])


  const layoutAsidePadding = isConstructorFullscreen ? '' : 'lg:pl-60'
  const layoutTopPadding = isConstructorFullscreen ? '' : 'pt-14'
  const mobileAsideShift = !isConstructorFullscreen && isAsideMobileExpanded ? 'ml-60 lg:ml-0' : ''

  return (
    <div className={`${darkMode ? 'dark' : ''} overflow-hidden lg:overflow-visible`}>
      <div
        className={`${layoutAsidePadding} ${mobileAsideShift} ${layoutTopPadding} min-h-screen w-screen transition-position lg:w-auto ${bgColor} dark:bg-dark-800 dark:text-slate-100`}
      >
        {!isConstructorFullscreen && (
          <>
            <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>
              <NavBarItemPlain
                display="hidden"
                onClick={() => setIsAsideLgActive(true)}
              >
                <BaseIcon path={mdiMenu} size="24" />
              </NavBarItemPlain>
              <NavBarItemPlain useMargin>
                <Search />
              </NavBarItemPlain>
            </NavBar>
            <AsideMenu
              isAsideMobileExpanded={isAsideMobileExpanded}
              isAsideLgActive={isAsideLgActive}
              menu={menuAside}
              onAsideLgClose={() => setIsAsideLgActive(false)}
            />
          </>
        )}
        {children}
        {!isConstructorFullscreen && <FooterBar>Hand-crafted & Made with ❤️</FooterBar>}
      </div>
    </div>
  )
}
