import { useQuery } from 'convex/react';
import { useRef, type ReactNode } from 'react';
import { useLocation } from 'react-router-dom';
import { api } from '../../../../../convex/_generated/api';
import { useIsMobile } from '../../hooks/useIsMobile';
import { useMobileSwipeNav } from '../../hooks/useMobileSwipeNav';
import { FileUploadDropZone } from '../channel/FileUploadDropZone';
import { ChannelView } from '../channel/ChannelView';
import { DMLayout } from '../dm/DMLayout';
import { GuildList } from './GuildList';
import { GuildNavbar } from './GuildNavbar';
import { MobileBottomNav } from './MobileBottomNav';
import { UserArea } from './UserArea';
import styles from './GuildsLayout.module.css';

interface GuildsLayoutProps {
	children: ReactNode;
}

/**
 * Parse the current pathname to decide which mobile view to show. At
 * ≤768px exactly one of the three columns is visible at a time.
 *   /channels/@me                → nav   (DM list)
 *   /channels/@me/:channelId     → chat
 *   /channels/:serverId          → nav   (channel list)
 *   /channels/:serverId/:channelId → chat
 *   /channels/you                → you   (mobile profile tab)
 */
function detectMobileMode(pathname: string): 'nav' | 'chat' | 'you' {
	const segments = pathname.split('/').filter(Boolean);
	if (segments[0] !== 'channels') return 'nav';
	if (segments[1] === 'you') return 'you';
	return segments.length >= 3 && !!segments[2] ? 'chat' : 'nav';
}

export function GuildsLayout({ children }: GuildsLayoutProps) {
	const location = useLocation();
	const segments = location.pathname.split('/').filter(Boolean);
	// /channels/:serverId/... — serverId is segments[1], '@me' for DMs
	const serverId = segments[0] === 'channels' ? segments[1] : undefined;
	const channelId = segments[0] === 'channels' ? segments[2] : undefined;
	const hasServer = !!serverId && serverId !== '@me' && serverId !== 'you';
	const mobileMode = detectMobileMode(location.pathname);

	const isMobile = useIsMobile();
	const wrapperRef = useRef<HTMLDivElement>(null);
	const containerRef = useRef<HTMLDivElement>(null);
	useMobileSwipeNav(containerRef, wrapperRef);

	// On mobile nav mode, pre-render the last-viewed channel so the
	// swipe preview shows actual chat content instead of the "Select a
	// channel" placeholder. The remembered channelId comes from the
	// same localStorage key the swipe hook writes.
	const rememberedChannelId =
		isMobile && mobileMode === 'nav' && serverId
			? (() => {
					try {
						return localStorage.getItem(`brycord:lastChannel:${serverId}`);
					} catch {
						return null;
					}
				})()
			: null;

	// Look up the current channel's name + type so the drop overlay
	// reads "Upload to #channel-name". Drops are disabled when there's
	// no channel in the URL (DM home, `/you` profile) and on voice
	// channels — they have no composer to attach to.
	const channel = useQuery(
		api.channels.get,
		channelId ? { id: channelId as any } : 'skip',
	);
	const channelName = (channel && (channel as any).name) || 'channel';
	const channelType = (channel && (channel as any).type) || undefined;
	const dropDisabled = !channelId || channelType === 'voice' || channelType === 'category';

	return (
		<FileUploadDropZone
			channelName={channelName}
			disabled={dropDisabled}
			onDropFiles={(files) => {
				if (!channelId) return;
				window.dispatchEvent(
					new CustomEvent('brycord:drop-files', {
						detail: { channelId, files },
					}),
				);
			}}
		>
			<div className={styles.wrapper} data-mobile-mode={mobileMode} ref={wrapperRef}>
				<div className={styles.container} ref={containerRef}>
					<div className={styles.guildList}>
						<GuildList />
					</div>
					<div className={styles.sidebar}>
						{hasServer ? <GuildNavbar /> : <DMLayout />}
					</div>
					<div className={styles.sidebarDivider} />
					<div className={styles.content}>
						{rememberedChannelId ? (
							<ChannelView channelId={rememberedChannelId} />
						) : (
							children
						)}
					</div>
					<div className={styles.userAreaWrapper}>
						<UserArea />
					</div>
				</div>
				<MobileBottomNav />
			</div>
		</FileUploadDropZone>
	);
}
