import { cva, type VariantProps } from "class-variance-authority";
import { Check, CheckCheck } from "lucide-react";
import * as React from "react";
import MessageLoading from "~/components/chat/message-loading";
import { Button, type ButtonProps } from "~/components/ui/button";
import { cn } from "~/lib/utils";

// ChatBubble
const chatBubbleVariant = cva(
	"flex gap-2 max-w-[60%] items-end relative group",
	{
		defaultVariants: {
			layout: "default",
			variant: "received",
		},
		variants: {
			layout: {
				ai: "max-w-full w-full items-center",
				default: "",
			},
			variant: {
				received: "self-start",
				sent: "self-end flex-row-reverse",
			},
		},
	},
);

interface ChatBubbleProps
	extends React.HTMLAttributes<HTMLDivElement>,
		VariantProps<typeof chatBubbleVariant> {}

const ChatBubble = React.forwardRef<HTMLDivElement, ChatBubbleProps>(
	({ className, variant, layout, children, ...props }, ref) => (
		<div
			className={cn(
				chatBubbleVariant({ className, layout, variant }),
				"group relative",
			)}
			ref={ref}
			{...props}
		>
			{React.Children.map(children, (child) =>
				React.isValidElement(child) && typeof child.type !== "string"
					? React.cloneElement(child, {
							layout,
							variant,
						} as Partial<React.ComponentProps<typeof child.type>>)
					: child,
			)}
		</div>
	),
);
ChatBubble.displayName = "ChatBubble";

type ChatBubbleReadStatusProps = {
	isread: boolean;
};

export const ChatBubbleReadStatus = ({ isread }: ChatBubbleReadStatusProps) => {
	if (isread) {
		return <CheckCheck className="mt-2 size-4 text-green-500" />;
	}
	return <Check className="mt-2 size-4 text-muted-foreground" />;
};

// ChatBubbleMessage
const chatBubbleMessageVariants = cva("p-2", {
	defaultVariants: {
		layout: "default",
		variant: "received",
	},
	variants: {
		layout: {
			ai: "border-t w-full rounded-none bg-transparent",
			default: "",
		},
		variant: {
			received:
				"bg-secondary text-secondary-foreground rounded-r-lg rounded-tl-lg",
			sent: "bg-primary text-primary-foreground rounded-l-lg rounded-tr-lg",
		},
	},
});

interface ChatBubbleMessageProps
	extends React.HTMLAttributes<HTMLDivElement>,
		VariantProps<typeof chatBubbleMessageVariants> {
	isLoading?: boolean;
}

const ChatBubbleMessage = React.forwardRef<
	HTMLDivElement,
	ChatBubbleMessageProps
>(
	(
		{ className, variant, layout, isLoading = false, children, ...props },
		ref,
	) => (
		<div
			className={cn(
				chatBubbleMessageVariants({ className, layout, variant }),
				"wrap-break-word max-w-full whitespace-pre-wrap",
			)}
			ref={ref}
			{...props}
		>
			{isLoading ? (
				<div className="flex items-center space-x-2">
					<MessageLoading />
				</div>
			) : (
				children
			)}
		</div>
	),
);
ChatBubbleMessage.displayName = "ChatBubbleMessage";

// ChatBubbleTimestamp
interface ChatBubbleTimestampProps
	extends React.HTMLAttributes<HTMLDivElement> {
	timestamp: string;
}

const ChatBubbleTimestamp: React.FC<ChatBubbleTimestampProps> = ({
	timestamp,
	className,
	...props
}) => (
	<div className={cn("mt-2 text-right text-xs", className)} {...props}>
		{timestamp}
	</div>
);

// ChatBubbleAction
type ChatBubbleActionProps = ButtonProps & {
	icon: React.ReactNode;
};

const ChatBubbleAction: React.FC<ChatBubbleActionProps> = ({
	icon,
	onClick,
	className,
	variant = "ghost",
	size = "icon",
	...props
}) => (
	<Button
		aria-label="Chat Bubble Action"
		className={className}
		onClick={onClick}
		size={size}
		variant={variant}
		{...props}
	>
		{icon}
	</Button>
);

interface ChatBubbleActionWrapperProps
	extends React.HTMLAttributes<HTMLDivElement> {
	variant?: "sent" | "received";
	className?: string;
	show: boolean;
}

const ChatBubbleActionWrapper = React.forwardRef<
	HTMLDivElement,
	ChatBubbleActionWrapperProps
>(({ variant, className, show, children, ...props }, ref) => (
	<>
		{show && (
			<div
				className={cn(
					"absolute top-1/2 flex -translate-y-1/2 opacity-0 transition-opacity duration-200 group-hover:opacity-100",
					variant === "sent"
						? "-left-1 -translate-x-full flex-row-reverse"
						: "-right-1 translate-x-full",
					className,
				)}
				ref={ref}
				{...props}
			>
				{children}
			</div>
		)}
	</>
));
ChatBubbleActionWrapper.displayName = "ChatBubbleActionWrapper";

export {
	ChatBubble,
	ChatBubbleMessage,
	ChatBubbleTimestamp,
	ChatBubbleAction,
	ChatBubbleActionWrapper,
};
