import React, { useEffect, useState, lazy, Suspense } from 'react';
import { Navigate, Route, Routes, useNavigate } from 'react-router-dom';

import './css/App.css';
import Home from './pages/home/Home';
import ErrorBoundary from './util/ErrorBoundary';
import Sidebar, { SidebarMenu } from './components/Sidebar';
import UserControls from './components/UserControls';
import { useLoginContext } from './structures/UserContext';
import Login from './pages/Login';
import { get, setSession, setSettings } from './util/Util';
import { PrivateRoute } from './structures/PrivateRoute';
import { UnauthedRoute } from './structures/UnauthedRoute';
import TitledPage from './components/TitledPage';
import Register from './pages/Register';
import { ClientSettings, SidebarMenuItem } from './@types/Other';
import { User } from './@types/ApiStructures';
import { PermissionBarrier } from './structures/PermissionBarrier';
import Recover from './pages/Recover';
// import OnlineList from './components/OnlineList';
// import socket, { updateState } from './util/Socket';

const Admin = lazy(() => import(/* webpackChunkName: "admin" */'./pages/admin/Admin'));
// const Moderation = lazy(() => import(/* webpackChunkName: "moderation" */'./pages/moderation/Moderation'));
// const Logs = lazy(() => import(/* webpackChunkName: "logs" */'./pages/logs/Logs'));
// const Servers = lazy(() => import(/* webpackChunkName: "servers" */'./pages/Servers'));

const Loading = () =>
{
    return (<div>Loading...</div>);
};

const ErrorFallback = () =>
{
    return <h3>
        Failed to load major component.
    </h3>;
};

const App = () =>
{
    const [ user, updateUser ] = useLoginContext();
    const [ loading, setLoading ] = useState(true);
    const navigate = useNavigate();

    useEffect(() =>
    {
        (async () =>
        {
            const result = await get<{twoFactor: boolean}>('/api/user');
            if (result.status === 200)
            {
                setSession(result.data as User);
                updateUser();
            }

            setLoading(false);
            if (result.status === 401 && result.data?.twoFactor)
                return navigate('/login/verify');
        })();
    }, []);

    useEffect(() =>
    {
        // socket.connect();
        (async () =>
        {
            const settings = await get('/api/settings');
            setSettings(settings.data as ClientSettings);
            // updateState();
        })();
        return () =>
        {
            // socket.disconnect();
        };
    }, [ user ]);

    const menuItems: SidebarMenuItem[] = [
        {
            to: '/home', label: 'Home', items: [
                { to: '/profile', label: 'Profile', relative: true },
                { to: '/applications', label: 'Applications', relative: true, permission: [ 'applications:*', 1 ] }
            ]
        },
        {
            to: '/admin', label: 'Admin', permission: [ 'administrator:*', 1 ], items: [
                { to: '/users', label: 'Users', relative: true, permission: [ 'administrator:users:*', 1 ] },
                { to: '/roles', label: 'Roles', relative: true, permission: [ 'administrator:roles:*', 1 ] },
                { to: '/flags', label: 'Flags', relative: true, permission: [ 'administrator:flags:*', 1 ] },
                // { to: '/crs', label: 'Canned Responses', relative: true, permission: [ 'administrator:crs:*', 1 ] },
            ]
        }
    ];

    if (loading)
        return null;

    return (
        <div className='app'>
            <div className='background'>

                {user ?
                    <div>
                        <header className="">
                            {/* <OnlineList /> */}
                            <UserControls />
                        </header>
                        <Sidebar>
                            <SidebarMenu menuItems={menuItems} />
                        </Sidebar>
                    </div>
                    : null}

                <div className={`main-content ${user ? '' : 'login'}`}>

                    <ErrorBoundary fallback={<ErrorFallback />}>

                        <Routes>
                            <Route path='/home/*' element={<PrivateRoute>
                                <TitledPage title='Home'>
                                    <Home />
                                </TitledPage>
                            </PrivateRoute >} />

                            <Route path='/admin/*' element={<PrivateRoute>
                                <TitledPage title='Admin'>
                                    <PermissionBarrier permission='administrator:*' level={1}>
                                        <Suspense fallback={<Loading />}>
                                            <Admin />
                                        </Suspense>
                                    </PermissionBarrier>
                                </TitledPage>

                            </PrivateRoute >} />

                            <Route path='/login/*' element={<UnauthedRoute>
                                <Login title='Log In'/>
                            </UnauthedRoute>} />

                            <Route path='/register/*' element={<UnauthedRoute>
                                <Register title='Register'/>
                            </UnauthedRoute>} />

                            <Route path='/recover/*' element={
                                <UnauthedRoute>
                                    <Recover title='Recover your password'/>
                                </UnauthedRoute>
                            } />

                            <Route path='*' element={<Navigate to='/home' />} />
                        </Routes>

                    </ErrorBoundary>

                    <div className={`footer ${user ? '' : 'login'}`}>
                        <p className='m-0 text-center'>Made with <i className="icon corgi transparent"></i> by <a href="https://corgi.wtf" target="_blank" rel="noreferrer">Navy.gif</a> &nbsp;|&nbsp; Front-end magic by <a href="https://d3vision.dev" target="_blank" rel="noreferrer">D3vision</a></p>
                    </div>
                </div>

            </div>
        </div>
    );
};

export default App;
