/**
 * JTZL_WebIRC_Chat - Channel Sidebar Component
 *
 * @package   JTZL_WebIRC_Chat
 * @copyright Copyright (c) 2025, JT. G.
 * @license   GPL-3.0+
 * @since     3.0.0
 */

import * as React from 'react';
import { memo } from 'react';
import { Hash, Users, Wifi, WifiOff, AlertCircle, Loader2 } from 'lucide-react';
import { cn } from '../../lib/utils';
import type { Channel, User } from '../../types/components';

export interface ChannelSidebarProps {
	channels: Channel[];
	users: User[];
	currentChannel: string;
	isConnected: boolean;
	connectionStatus: 'disconnected' | 'connecting' | 'connected' | 'error';
	onChannelSelect: (channel: string) => void;
	onUserSelect: (user: string) => void;
	serverAddress?: string;
	className?: string;
}

/**
 * Get connection status icon based on current status.
 *
 * @since 3.0.0
 *
 * @param status - Current connection status
 * @return JSX.Element - Status icon component
 */
function getConnectionIcon(status: ChannelSidebarProps['connectionStatus']) {
	switch (status) {
		case 'connected':
			return <Wifi className="h-4 w-4 text-green-500" />;
		case 'connecting':
			return <Loader2 className="h-4 w-4 text-yellow-500 animate-spin" />;
		case 'error':
			return <AlertCircle className="h-4 w-4 text-red-500" />;
		case 'disconnected':
		default:
			return <WifiOff className="h-4 w-4 text-gray-500" />;
	}
}

/**
 * Get user status indicator color based on status.
 * Updated to match v0 app styling.
 *
 * @since 3.0.0
 *
 * @param status - User status
 * @return string - CSS color class
 */
function getUserStatusColor(status: User['status']): string {
	switch (status) {
		case 'online':
			return 'bg-accent';
		case 'away':
			return 'bg-yellow-500';
		case 'offline':
		default:
			return 'bg-muted-foreground';
	}
}

/**
 * Get user privilege prefix based on IRC modes.
 *
 * @since 3.0.0
 *
 * @param user - User object with privilege flags
 * @return string - Privilege prefix character
 */
function getUserPrefix(user: User): string {
	if (user.isOwner) return '~';
	if (user.isOp) return '@';
	if (user.isHalfOp) return '%';
	if (user.isVoice) return '+';
	return '';
}

/**
 * Get connection status text based on current status.
 *
 * @since 3.0.0
 *
 * @param status - Current connection status
 * @return string - Status text
 */
function getConnectionStatusText(
	status: ChannelSidebarProps['connectionStatus']
): string {
	switch (status) {
		case 'connected':
			return 'Connected';
		case 'connecting':
			return 'Connecting...';
		case 'error':
			return 'Error';
		case 'disconnected':
		default:
			return 'Disconnected';
	}
}

/**
 * Individual channel item component with memoization.
 *
 * @since 3.0.0
 */
const ChannelItem = memo(
	({
		channel,
		currentChannel,
		isConnected,
		onChannelSelect,
	}: {
		channel: Channel;
		currentChannel: string;
		isConnected: boolean;
		onChannelSelect: (channel: string) => void;
	}) => (
		<button
			onClick={() => onChannelSelect(channel.name)}
			disabled={!isConnected}
			className={cn(
				'w-full text-left px-2 py-1.5 rounded text-sm transition-colors',
				currentChannel === channel.name
					? 'bg-sidebar-primary text-sidebar-primary-foreground'
					: 'text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground'
			)}
		>
			<div className="flex items-center justify-between">
				<span>{channel.name}</span>
				{channel.userCount !== undefined && (
					<span className="text-xs opacity-70">
						{channel.userCount}
					</span>
				)}
			</div>
			{channel.topic && (
				<div className="text-xs opacity-70 truncate mt-0.5">
					{channel.topic}
				</div>
			)}
		</button>
	)
);

ChannelItem.displayName = 'ChannelItem';

/**
 * Individual user item component with memoization.
 *
 * @since 3.0.0
 */
const UserItem = memo(
	({
		user,
		isConnected,
		onUserSelect,
	}: {
		user: User;
		isConnected: boolean;
		onUserSelect: (user: string) => void;
	}) => (
		<button
			onClick={() => onUserSelect(user.nick)}
			disabled={!isConnected}
			className="flex items-center gap-2 px-2 py-1 text-sm text-sidebar-foreground w-full text-left hover:bg-sidebar-accent hover:text-sidebar-accent-foreground rounded transition-colors"
		>
			<div
				className={cn(
					'w-2 h-2 rounded-full',
					getUserStatusColor(user.status)
				)}
			/>
			<span>
				{getUserPrefix(user)}
				{user.nick}
			</span>
		</button>
	)
);

UserItem.displayName = 'UserItem';

/**
 * Channel Sidebar component for displaying channels and users.
 * Updated to match v0 app exact styling.
 *
 * @since 3.0.0
 *
 * @return JSX.Element - Rendered channel sidebar component
 */
const ChannelSidebarComponent = function ChannelSidebar({
	channels,
	users,
	currentChannel,
	isConnected,
	connectionStatus,
	onChannelSelect,
	onUserSelect,
	serverAddress,
	className,
}: ChannelSidebarProps) {
	/**
	 * Handle channel selection.
	 *
	 * @since 3.0.0
	 *
	 * @param channel - Channel name to select
	 */
	const handleChannelSelect = React.useCallback(
		(channel: string) => {
			onChannelSelect(channel);
		},
		[onChannelSelect]
	);

	/**
	 * Handle user selection for private messages.
	 *
	 * @since 3.0.0
	 *
	 * @param user - Username to start private message with
	 */
	const handleUserSelect = React.useCallback(
		(user: string) => {
			onUserSelect(user);
		},
		[onUserSelect]
	);

	return (
		<div className={cn('flex flex-col h-full', className)}>
			{/* Connection Status Header */}
			<div className="p-3 border-b border-sidebar-border h-[60px] flex items-center">
				<div className="flex items-center gap-2 w-full">
					{getConnectionIcon(connectionStatus)}
					<div className="flex flex-col min-w-0 flex-1">
						<span className="text-sm font-medium text-sidebar-foreground leading-tight">
							{getConnectionStatusText(connectionStatus)}
						</span>
						<span className="text-xs text-muted-foreground truncate leading-tight">
							{serverAddress || 'Not configured'}
						</span>
					</div>
				</div>
			</div>

			<div className="flex-1 overflow-hidden">
				{/* Channels Section */}
				<div className="p-3 border-b border-sidebar-border">
					<h3 className="text-sm font-semibold text-sidebar-foreground mb-2 flex items-center gap-2">
						<Hash className="h-4 w-4" />
						Channels
					</h3>
					<div className="h-32 overflow-y-auto">
						<div className="space-y-1">
							{channels.map((channel) => (
								<ChannelItem
									key={channel.name}
									channel={channel}
									currentChannel={currentChannel}
									isConnected={isConnected}
									onChannelSelect={handleChannelSelect}
								/>
							))}
						</div>
					</div>
				</div>

				{/* Users Section */}
				<div className="p-3">
					<h3 className="text-sm font-semibold text-sidebar-foreground mb-2 flex items-center gap-2">
						<Users className="h-4 w-4" />
						Users
						{users.length > 0 && (
							<span className="text-xs text-muted-foreground">
								({users.length})
							</span>
						)}
					</h3>
					<div className="h-40 overflow-y-auto">
						<div className="space-y-1">
							{users.map((user) => (
								<UserItem
									key={user.nick}
									user={user}
									isConnected={isConnected}
									onUserSelect={handleUserSelect}
								/>
							))}
						</div>
					</div>
				</div>
			</div>
		</div>
	);
};

// Export memoized version to prevent unnecessary re-renders
export const ChannelSidebar = memo(ChannelSidebarComponent);
