import React, { ReactNode, useEffect, useRef, useState } from 'react';
import jwt from 'jsonwebtoken';
import axios from 'axios';
import { toast } from 'react-toastify';
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 { logger } from '../lib/logger';

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

// Routes that require at least one project to exist
const ROUTES_REQUIRING_PROJECT = [
  '/access_logs',
  '/assets',
  '/asset_variants',
  '/presigned_url_requests',
  '/project_audio_tracks',
  '/project_memberships',
  '/publish_events',
  '/pwa_caches',
  '/tour_pages',
];

type Props = {
  children: ReactNode;
  permission?: string;
  /** Render only auth check, no sidebar/header/footer (for presentations) */
  minimal?: boolean;
};

export default function LayoutAuthenticated({
  children,
  permission,
  minimal = false,
}: Props) {
  const dispatch = useAppDispatch();
  const router = useRouter();
  const { token, currentUser, isFetching } = useAppSelector(
    (state) => state.auth,
  );
  const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
  const darkMode = useAppSelector((state) => state.style.darkMode);
  const meRequestedRef = useRef<string | null>(null);
  const [isAuthChecked, setIsAuthChecked] = useState(false);
  const [isAsideMobileExpanded, setIsAsideMobileExpanded] = useState(false);
  const [isAsideLgActive, setIsAsideLgActive] = useState(false);

  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) {
      logger.error(
        'Failed to decode auth token:',
        error instanceof Error ? error : { 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());
    } else if (currentUser) {
      setIsAuthChecked(true);
    }
  }, [router.isReady, router.pathname, token, currentUser, dispatch]);

  // Mark auth as checked once currentUser is loaded
  useEffect(() => {
    if (currentUser && !isFetching) {
      setIsAuthChecked(true);
    }
  }, [currentUser, isFetching]);

  // Check if projects exist for routes that require them
  useEffect(() => {
    if (!isAuthChecked || !router.isReady) return;

    const requiresProject = ROUTES_REQUIRING_PROJECT.some((route) =>
      router.pathname.startsWith(route),
    );

    if (!requiresProject) return;

    const checkProjects = async () => {
      try {
        const response = await axios.get('/projects/autocomplete?limit=1');
        const projects = Array.isArray(response?.data) ? response.data : [];
        if (projects.length === 0) {
          toast('Please create a project first', {
            type: 'info',
            position: 'bottom-center',
          });
          router.replace('/projects/projects-new');
        }
      } catch (error) {
        logger.error(
          'Failed to check projects:',
          error instanceof Error ? error : { error },
        );
      }
    };

    checkProjects();
  }, [isAuthChecked, router.isReady, router.pathname]);

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

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

  const isConstructorFullscreen = router.pathname === '/constructor';

  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' : '';

  // Minimal mode: just auth check, no UI chrome (for presentations)
  if (minimal) {
    return <>{children}</>;
  }

  // Show loading while auth is being checked
  if (!isAuthChecked) {
    return (
      <div
        className={`${darkMode ? 'dark' : ''} overflow-hidden lg:overflow-visible`}
      >
        <div
          className={`min-h-screen w-screen flex items-center justify-center ${bgColor} dark:bg-dark-800 dark:text-slate-100`}
        >
          <div className='text-center'>
            <div className='animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900 dark:border-white mx-auto mb-4'></div>
            <p>Loading...</p>
          </div>
        </div>
      </div>
    );
  }

  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>
  );
}
