/**
 * JTZL_WebIRC_Chat - 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 { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '../../lib/utils';
import { useSidebar } from './sidebar-provider';

const sidebarVariants = cva(
	'group/sidebar relative flex h-full w-full flex-col bg-sidebar text-sidebar-foreground',
	{
		variants: {
			variant: {
				sidebar: 'bg-sidebar text-sidebar-foreground',
				floating:
					'bg-sidebar text-sidebar-foreground shadow-lg border border-sidebar-border rounded-lg',
				inset: 'bg-sidebar/50 text-sidebar-foreground',
			},
			side: {
				left: '',
				right: '',
			},
			collapsible: {
				offcanvas: '',
				icon: '',
				none: '',
			},
		},
		defaultVariants: {
			variant: 'sidebar',
			side: 'left',
			collapsible: 'offcanvas',
		},
	}
);

export interface SidebarProps
	extends React.HTMLAttributes<HTMLDivElement>,
		VariantProps<typeof sidebarVariants> {
	collapsed?: boolean;
}

/**
 * Main Sidebar component container.
 *
 * @since 3.0.0
 *
 * @param props - Sidebar component props
 * @return JSX.Element - Rendered sidebar component
 */
const Sidebar = React.forwardRef<HTMLDivElement, SidebarProps>(
	(
		{ className, variant, side, collapsible, collapsed = false, ...props },
		ref
	) => {
		return (
			<div
				ref={ref}
				data-sidebar="sidebar"
				data-collapsible={collapsible}
				data-variant={variant}
				data-side={side}
				data-collapsed={collapsed}
				className={cn(
					sidebarVariants({ variant, side, collapsible }),
					collapsed && collapsible === 'icon' && 'w-12',
					!collapsed && 'w-64',
					className
				)}
				{...props}
			/>
		);
	}
);
Sidebar.displayName = 'Sidebar';

export interface SidebarHeaderProps
	extends React.HTMLAttributes<HTMLDivElement> {
	sticky?: boolean;
}

/**
 * Sidebar header component for title and controls.
 *
 * @since 3.0.0
 *
 * @param props - SidebarHeader component props
 * @return JSX.Element - Rendered sidebar header component
 */
const SidebarHeader = React.forwardRef<HTMLDivElement, SidebarHeaderProps>(
	({ className, ...props }, ref) => {
		return (
			<div
				ref={ref}
				data-sidebar="header"
				className={cn(
					'flex items-center gap-2 px-4 py-2 border-b border-sidebar-border',
					className
				)}
				{...props}
			/>
		);
	}
);
SidebarHeader.displayName = 'SidebarHeader';

export interface SidebarContentProps
	extends React.HTMLAttributes<HTMLDivElement> {
	scrollable?: boolean;
}

/**
 * Sidebar content area for main navigation items.
 *
 * @since 3.0.0
 *
 * @param props - SidebarContent component props
 * @return JSX.Element - Rendered sidebar content component
 */
const SidebarContent = React.forwardRef<HTMLDivElement, SidebarContentProps>(
	({ className, ...props }, ref) => {
		return (
			<div
				ref={ref}
				data-sidebar="content"
				className={cn(
					'flex flex-1 flex-col gap-2 overflow-auto p-2',
					className
				)}
				{...props}
			/>
		);
	}
);
SidebarContent.displayName = 'SidebarContent';

export interface SidebarFooterProps
	extends React.HTMLAttributes<HTMLDivElement> {
	sticky?: boolean;
}

/**
 * Sidebar footer component for bottom actions.
 *
 * @since 3.0.0
 *
 * @param props - SidebarFooter component props
 * @return JSX.Element - Rendered sidebar footer component
 */
const SidebarFooter = React.forwardRef<HTMLDivElement, SidebarFooterProps>(
	({ className, ...props }, ref) => {
		return (
			<div
				ref={ref}
				data-sidebar="footer"
				className={cn(
					'flex items-center gap-2 px-4 py-2 border-t border-sidebar-border',
					className
				)}
				{...props}
			/>
		);
	}
);
SidebarFooter.displayName = 'SidebarFooter';

export interface SidebarGroupProps
	extends React.HTMLAttributes<HTMLDivElement> {
	collapsible?: boolean;
}

/**
 * Sidebar group component for organizing related items.
 *
 * @since 3.0.0
 *
 * @param props - SidebarGroup component props
 * @return JSX.Element - Rendered sidebar group component
 */
const SidebarGroup = React.forwardRef<HTMLDivElement, SidebarGroupProps>(
	({ className, ...props }, ref) => {
		return (
			<div
				ref={ref}
				data-sidebar="group"
				className={cn(
					'relative flex w-full min-w-0 flex-col p-2',
					className
				)}
				{...props}
			/>
		);
	}
);
SidebarGroup.displayName = 'SidebarGroup';

export interface SidebarGroupLabelProps
	extends React.HTMLAttributes<HTMLDivElement> {
	asChild?: boolean;
}

/**
 * Sidebar group label component for section titles.
 *
 * @since 3.0.0
 *
 * @param props - SidebarGroupLabel component props
 * @return JSX.Element - Rendered sidebar group label component
 */
const SidebarGroupLabel = React.forwardRef<
	HTMLDivElement,
	SidebarGroupLabelProps
>(({ className, ...props }, ref) => {
	return (
		<div
			ref={ref}
			data-sidebar="group-label"
			className={cn(
				'duration-200 relative flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 outline-none ring-sidebar-ring transition-[margin,opa] ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
				className
			)}
			{...props}
		/>
	);
});
SidebarGroupLabel.displayName = 'SidebarGroupLabel';

export interface SidebarGroupContentProps
	extends React.HTMLAttributes<HTMLDivElement> {
	asChild?: boolean;
}

/**
 * Sidebar group content component for group items.
 *
 * @since 3.0.0
 *
 * @param props - SidebarGroupContent component props
 * @return JSX.Element - Rendered sidebar group content component
 */
const SidebarGroupContent = React.forwardRef<
	HTMLDivElement,
	SidebarGroupContentProps
>(({ className, ...props }, ref) => {
	return (
		<div
			ref={ref}
			data-sidebar="group-content"
			className={cn('w-full text-sm', className)}
			{...props}
		/>
	);
});
SidebarGroupContent.displayName = 'SidebarGroupContent';

export interface SidebarMenuProps
	extends React.HTMLAttributes<HTMLUListElement> {
	asChild?: boolean;
}

/**
 * Sidebar menu component for navigation lists.
 *
 * @since 3.0.0
 *
 * @param props - SidebarMenu component props
 * @return JSX.Element - Rendered sidebar menu component
 */
const SidebarMenu = React.forwardRef<HTMLUListElement, SidebarMenuProps>(
	({ className, ...props }, ref) => {
		return (
			<ul
				ref={ref}
				data-sidebar="menu"
				className={cn('flex w-full min-w-0 flex-col gap-1', className)}
				{...props}
			/>
		);
	}
);
SidebarMenu.displayName = 'SidebarMenu';

export interface SidebarMenuItemProps
	extends React.HTMLAttributes<HTMLLIElement> {
	asChild?: boolean;
}

/**
 * Sidebar menu item component for individual navigation items.
 *
 * @since 3.0.0
 *
 * @param props - SidebarMenuItem component props
 * @return JSX.Element - Rendered sidebar menu item component
 */
const SidebarMenuItem = React.forwardRef<HTMLLIElement, SidebarMenuItemProps>(
	({ className, ...props }, ref) => {
		return (
			<li
				ref={ref}
				data-sidebar="menu-item"
				className={cn('group/menu-item relative', className)}
				{...props}
			/>
		);
	}
);
SidebarMenuItem.displayName = 'SidebarMenuItem';

const sidebarMenuButtonVariants = cva(
	'peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0',
	{
		variants: {
			variant: {
				default:
					'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',
				outline:
					'bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]',
			},
			size: {
				default: 'h-8 text-sm',
				sm: 'h-7 text-xs',
				lg: 'h-12 text-sm group-data-[collapsible=icon]:!p-0',
			},
		},
		defaultVariants: {
			variant: 'default',
			size: 'default',
		},
	}
);

export interface SidebarMenuButtonProps
	extends React.ButtonHTMLAttributes<HTMLButtonElement>,
		VariantProps<typeof sidebarMenuButtonVariants> {
	asChild?: boolean;
	isActive?: boolean;
	tooltip?: string;
}

/**
 * Sidebar menu button component for clickable navigation items.
 *
 * @since 3.0.0
 *
 * @param props - SidebarMenuButton component props
 * @return JSX.Element - Rendered sidebar menu button component
 */
const SidebarMenuButton = React.forwardRef<
	HTMLButtonElement,
	SidebarMenuButtonProps
>(
	(
		{
			asChild = false,
			isActive = false,
			variant = 'default',
			size = 'default',
			tooltip,
			className,
			...props
		},
		ref
	) => {
		const Comp = asChild ? 'span' : 'button';

		return (
			<Comp
				ref={ref}
				data-sidebar="menu-button"
				data-size={size}
				data-active={isActive}
				className={cn(
					sidebarMenuButtonVariants({ variant, size }),
					className
				)}
				title={tooltip}
				{...props}
			/>
		);
	}
);
SidebarMenuButton.displayName = 'SidebarMenuButton';

export interface SidebarTriggerProps
	extends React.ButtonHTMLAttributes<HTMLButtonElement> {
	asChild?: boolean;
}

/**
 * Sidebar trigger component for toggling sidebar visibility.
 *
 * @since 3.0.0
 *
 * @param props - SidebarTrigger component props
 * @return JSX.Element - Rendered sidebar trigger component
 */
const SidebarTrigger = React.forwardRef<HTMLButtonElement, SidebarTriggerProps>(
	({ className, onClick, ...props }, ref) => {
		const { toggleSidebar } = useSidebar();

		const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
			toggleSidebar();
			onClick?.(e);
		};

		return (
			<button
				ref={ref}
				data-sidebar="trigger"
				className={cn(
					'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 h-7 w-7 p-0',
					className
				)}
				onClick={handleClick}
				{...props}
			/>
		);
	}
);
SidebarTrigger.displayName = 'SidebarTrigger';

export {
	Sidebar,
	SidebarHeader,
	SidebarContent,
	SidebarFooter,
	SidebarGroup,
	SidebarGroupLabel,
	SidebarGroupContent,
	SidebarMenu,
	SidebarMenuItem,
	SidebarMenuButton,
	SidebarTrigger,
	sidebarMenuButtonVariants,
};
