import { useEffect, useState, type ReactNode } from 'react';
import { Routes, Route, Navigate, useLocation, useNavigate } from 'react-router-dom';
import { IconContext } from '@phosphor-icons/react';
import { LoginPage } from './components/auth/LoginPage';
import { RegisterPage } from './components/auth/RegisterPage';
import { InviteAcceptPage } from './components/auth/InviteAcceptPage';
import { AppLayout } from './components/layout/AppLayout';
import { MobileYouPage } from './components/layout/MobileYouPage';
import { TitleBar } from './components/layout/TitleBar';
import { ChannelView } from './components/channel/ChannelView';
import Recovery from './pages/Recovery';
import { usePlatform } from './platform';
import { useSearch } from './contexts/SearchContext';
import { useSystemBars } from './hooks/useSystemBars';
import './global.css';

const THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1000;

type AuthState = 'loading' | 'authenticated' | 'unauthenticated';

function AuthGuard({ children }: { children: ReactNode }) {
	const [authState, setAuthState] = useState<AuthState>('loading');
	const location = useLocation();
	const navigate = useNavigate();
	const { session, settings } = usePlatform();
	const searchCtx = useSearch();
	useSystemBars(null);

	useEffect(() => {
		let cancelled = false;

		async function restoreSession() {
			if (sessionStorage.getItem('privateKey') && sessionStorage.getItem('signingKey')) {
				searchCtx?.initialize();
				if (!cancelled) setAuthState('authenticated');
				return;
			}

			if (session) {
				try {
					const savedSession = await session.load();
					if (savedSession && savedSession.savedAt && Date.now() - savedSession.savedAt < THIRTY_DAYS_MS) {
						localStorage.setItem('userId', savedSession.userId);
						localStorage.setItem('username', savedSession.username);
						if (savedSession.publicKey) localStorage.setItem('publicKey', savedSession.publicKey);
						sessionStorage.setItem('signingKey', savedSession.signingKey);
						sessionStorage.setItem('privateKey', savedSession.privateKey);
						if (savedSession.masterKey) sessionStorage.setItem('masterKey', savedSession.masterKey);
						if (savedSession.searchDbKey) sessionStorage.setItem('searchDbKey', savedSession.searchDbKey);
						searchCtx?.initialize();
						if (settings) {
							try {
								const savedPrefs = await settings.get(`userPrefs_${savedSession.userId}`);
								if (savedPrefs && typeof savedPrefs === 'object') {
									localStorage.setItem(`userPrefs_${savedSession.userId}`, JSON.stringify(savedPrefs));
								}
							} catch {}
						}
						if (!cancelled) setAuthState('authenticated');
						return;
					}
					if (savedSession?.savedAt) {
						await session.clear();
					}
				} catch (err) {
					console.error('Session restore failed:', err);
				}
			}

			if (!cancelled) setAuthState('unauthenticated');
		}

		restoreSession();
		return () => {
			cancelled = true;
		};
	}, []);

	useEffect(() => {
		if (authState === 'loading') return;

		const isAuthPage =
			location.pathname === '/login' ||
			location.pathname === '/register' ||
			location.pathname === '/recovery' ||
			location.pathname.startsWith('/invite/');
		const hasSession = !!(sessionStorage.getItem('privateKey') && sessionStorage.getItem('signingKey'));

		// Invite accept runs regardless of session — if the viewer is
		// already logged in, the InviteAcceptPage itself will forward
		// them home after stashing the keys. Don't redirect them away.
		const isInvitePage = location.pathname.startsWith('/invite/');

		if (hasSession && isAuthPage && !isInvitePage) {
			navigate('/channels/@me', { replace: true });
		} else if (!hasSession && !isAuthPage) {
			navigate('/login', { replace: true });
		}
	}, [authState, location.pathname]);

	if (authState === 'loading') {
		return (
			<div
				style={{
					display: 'flex',
					alignItems: 'center',
					justifyContent: 'center',
					height: '100vh',
					backgroundColor: 'var(--background-primary)',
					color: 'var(--text-primary)',
					fontSize: 16,
				}}
			>
				Loading...
			</div>
		);
	}

	return <>{children}</>;
}

function DMHomePage() {
	return (
		<div
			style={{
				display: 'flex',
				alignItems: 'center',
				justifyContent: 'center',
				flex: 1,
				color: 'var(--text-secondary)',
			}}
		>
			<div style={{ textAlign: 'center' }}>
				<h2 style={{ color: 'var(--text-primary)', marginBottom: 8 }}>Welcome to Brycord</h2>
				<p>Select a conversation or start a new one</p>
			</div>
		</div>
	);
}

function ServerPage() {
	return (
		<div
			style={{
				display: 'flex',
				alignItems: 'center',
				justifyContent: 'center',
				flex: 1,
				color: 'var(--text-secondary)',
			}}
		>
			<p>Select a channel to start chatting</p>
		</div>
	);
}

function App() {
	return (
		<IconContext.Provider value={{ color: 'currentColor', weight: 'fill' }}>
			<TitleBar />
			<AuthGuard>
				<Routes>
					<Route path="/login" element={<LoginPage />} />
					<Route path="/register" element={<RegisterPage />} />
					<Route path="/invite/:code" element={<InviteAcceptPage />} />
					<Route path="/recovery" element={<Recovery />} />
					<Route path="/channels/*" element={<AppLayout />}>
						<Route path="@me" element={<DMHomePage />} />
						<Route path="@me/:channelId" element={<ChannelView />} />
						<Route path="you" element={<MobileYouPage />} />
						<Route path=":serverId" element={<ServerPage />} />
						<Route path=":serverId/:channelId" element={<ChannelView />} />
					</Route>
					<Route path="*" element={<Navigate to="/channels/@me" replace />} />
				</Routes>
			</AuthGuard>
		</IconContext.Provider>
	);
}

export default App;
