import {
  mdiAccountCircle,
  mdiAccountGroup,
  mdiBookOpenVariant,
  mdiClose,
  mdiFileDocumentEditOutline,
  mdiFormTextbox,
  mdiLogout,
  mdiMenu,
  mdiShieldAccountOutline,
  mdiViewDashboardOutline,
} from '@mdi/js';
import jwt from 'jsonwebtoken';
import Link from 'next/link';
import { useRouter } from 'next/router';
import React, { ReactNode, useEffect, useState } from 'react';
import BaseIcon from '../components/BaseIcon';
import { hasPermission } from '../helpers/userPermissions';
import { findMe, logoutUser } from '../stores/authSlice';
import { useAppDispatch, useAppSelector } from '../stores/hooks';

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

const navItems = [
  {
    href: '/dashboard',
    icon: mdiViewDashboardOutline,
    label: 'Dashboard',
  },
  {
    href: '/clients',
    icon: mdiAccountGroup,
    label: 'Clients',
  },
  {
    href: '/session-memory',
    icon: mdiFileDocumentEditOutline,
    label: 'Session Memory',
  },
  {
    href: '/intake-leads',
    icon: mdiFormTextbox,
    label: 'Intake Leads',
  },
  {
    href: '/client-portal',
    icon: mdiBookOpenVariant,
    label: 'Client Portal',
  },
  {
    href: '/users/users-list',
    icon: mdiShieldAccountOutline,
    label: 'Team',
    permission: 'READ_USERS',
  },
  {
    href: '/profile',
    icon: mdiAccountCircle,
    label: 'Profile',
  },
];

export default function LayoutAuthenticated({ children, permission }: Props) {
  const dispatch = useAppDispatch();
  const router = useRouter();
  const { token, currentUser } = useAppSelector((state) => state.auth);
  const [isAsideOpen, setIsAsideOpen] = useState(false);
  const isClientUser = currentUser?.app_role?.name === 'Client';

  function getLocalToken() {
    if (typeof window === 'undefined') {
      return null;
    }

    return localStorage.getItem('token');
  }

  function isTokenValid() {
    const localToken = getLocalToken();
    if (!localToken) {
      return false;
    }

    const decodedToken = jwt.decode(localToken);
    if (!decodedToken || typeof decodedToken === 'string') {
      return false;
    }

    if (!decodedToken.exp) {
      return false;
    }

    const now = new Date().getTime() / 1000;
    return now < decodedToken.exp;
  }

  useEffect(() => {
    dispatch(findMe());

    if (!isTokenValid()) {
      dispatch(logoutUser());
      router.push('/login');
    }
  }, [token]);

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

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

  useEffect(() => {
    if (!isClientUser) {
      return;
    }

    if (
      router.pathname === '/client-portal' ||
      router.pathname === '/profile'
    ) {
      return;
    }

    router.push('/client-portal');
  }, [isClientUser, router.pathname]);

  useEffect(() => {
    function closeAside() {
      setIsAsideOpen(false);
    }

    router.events.on('routeChangeStart', closeAside);

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

  const visibleNavItems = navItems.filter((item) => {
    if (isClientUser) {
      return item.href === '/client-portal' || item.href === '/profile';
    }

    if (!item.permission) {
      return true;
    }

    if (!currentUser) {
      return false;
    }

    return hasPermission(currentUser, item.permission);
  });

  const activePath = router.pathname.split('/')[1];

  return (
    <div className='min-h-screen bg-[#fffdf9] text-[#19192d]'>
      <aside
        className={`fixed inset-y-0 left-0 z-40 w-64 border-r border-[#19192d]/10 bg-[#fffdf9] px-3 py-4 transition-transform duration-300 lg:translate-x-0 ${
          isAsideOpen ? 'translate-x-0' : '-translate-x-full'
        }`}
      >
        <div className='flex items-center justify-between'>
          <Link href='/dashboard' className='flex items-center gap-3'>
            <span className='grid h-8 w-8 place-items-center rounded-none border border-[#35b7a5]/50 bg-[#35b7a5] text-sm font-black text-white'>
              CW
            </span>
            <span>
              <span className='block text-sm font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'>
                AppWizzy
              </span>
              <span className='block text-lg font-semibold'>
                Coaching Workspace
              </span>
            </span>
          </Link>
          <button
            type='button'
            className='grid h-8 w-8 place-items-center rounded-none border border-[#19192d]/10 text-[#72798a] lg:hidden'
            onClick={() => setIsAsideOpen(false)}
          >
            <BaseIcon path={mdiClose} size={18} />
          </button>
        </div>

        <div className='mt-5 rounded-none border border-[#19192d]/10 bg-white p-6'>
          <p className='text-xs font-semibold uppercase tracking-[0.2em] text-[#35b7a5]'>
            Today
          </p>
          <p className='mt-2 text-sm leading-6 text-[#72798a]'>
            {isClientUser
              ? 'Review shared notes, commitments, and resources from your coach.'
              : 'Prepare, follow up, and keep every coaching relationship warm between sessions.'}
          </p>
        </div>

        <nav className='mt-4 space-y-1'>
          {visibleNavItems.map((item) => {
            const itemPath = item.href.split('/')[1];
            const isActive = itemPath === activePath;

            return (
              <Link
                key={item.href}
                href={item.href}
                className={`flex items-center gap-3 rounded-none px-4 py-3 text-sm font-semibold transition ${
                  isActive
                    ? 'bg-[#35b7a5] text-white'
                    : 'text-[#72798a] hover:bg-[#fffdf9] hover:text-[#19192d]'
                }`}
              >
                <BaseIcon path={item.icon} size={18} />
                <span>{item.label}</span>
              </Link>
            );
          })}
        </nav>

        <div className='absolute inset-x-4 bottom-5 rounded-none border border-[#19192d]/10 bg-[#fffdf9] p-6'>
          <p className='text-xs font-semibold uppercase tracking-[0.18em] text-[#35b7a5]'>
            Signed in
          </p>
          <p className='mt-2 truncate text-sm font-semibold'>
            {currentUser?.email || 'Workspace user'}
          </p>
          <button
            type='button'
            className='mt-4 flex w-full items-center justify-center gap-2 rounded-none bg-[#19192d] px-4 py-2 text-sm font-semibold text-white'
            onClick={() => {
              dispatch(logoutUser());
              router.push('/login');
            }}
          >
            <BaseIcon path={mdiLogout} size={18} />
            Log out
          </button>
        </div>
      </aside>

      {isAsideOpen && (
        <button
          type='button'
          aria-label='Close menu'
          className='fixed inset-0 z-30 bg-[#19192d]/40 lg:hidden'
          onClick={() => setIsAsideOpen(false)}
        />
      )}

      <div className='lg:pl-64'>
        <header className='sticky top-0 z-20 border-b border-[#19192d]/10/80 bg-[#fffdf9]/92 px-4 py-3 backdrop-blur lg:px-8'>
          <div className='flex items-center justify-between'>
            <button
              type='button'
              className='grid h-8 w-8 place-items-center rounded-none border border-[#19192d]/10 bg-white text-[#72798a] lg:hidden'
              onClick={() => setIsAsideOpen(true)}
            >
              <BaseIcon path={mdiMenu} size={18} />
            </button>
            <div className='hidden lg:block'>
              <p className='text-xs font-semibold uppercase tracking-[0.22em] text-[#35b7a5]'>
                Workspace status
              </p>
              <p className='mt-1 text-sm text-[#72798a]'>
                {isClientUser
                  ? 'Review your commitments, notes, and shared resources.'
                  : 'Review sessions, clients, tasks, and shared client materials.'}
              </p>
            </div>
            <Link
              href='/'
              className='rounded-none border border-[#19192d]/10 bg-white px-4 py-2 text-sm font-semibold text-[#19192d]'
            >
              Public site
            </Link>
          </div>
        </header>

        <main>{children}</main>
      </div>
    </div>
  );
}
