import CopyIcon from "@/icons/copy.svg?react";

import SuccessIcon from "@/icons/check-circle.svg?react";
import ErrorIcon from "@/icons/warning.svg?react";
import InfoIcon from "@/icons/info.svg?react";

import * as ToastPrimitives from "@radix-ui/react-toast";
import { type VariantProps, cva } from "class-variance-authority";
import * as React from "react";
import Close from "@/icons/x-mark.svg?react";

import { cn } from "@/lib/utils";
import clsx from "clsx";
import { useToast } from "@/lib/hooks/use-toast";

import Discord from "@/icons/discord.svg?react";
import Copy from "@/icons/copy.svg?react";
import { TextLink } from "./text-link";
import { LINKS } from "@/lib/constants";

const ToastProvider = ToastPrimitives.Provider;

const ToastViewport = React.forwardRef<
	React.ElementRef<typeof ToastPrimitives.Viewport>,
	React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>
>(({ className, ...props }, ref) => (
	<ToastPrimitives.Viewport
		ref={ref}
		className={cn(
			"fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
			className,
		)}
		{...props}
	/>
));
ToastViewport.displayName = ToastPrimitives.Viewport.displayName;

const toastVariants = cva(
	"group min-h-[88px] min-w-[300px] pointer-events-auto relative flex w-full items-center justify-between overflow-hidden rounded-2xl p-4 pr-4 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full dark:border-neutral-800",
	{
		variants: {
			variant: {
				success: "bg-fill-100",
				warning: "bg-fill-100",
				error: "bg-fill-100",
				info: "bg-fill-100",
			},
		},
		defaultVariants: {
			variant: "success",
		},
	},
);

const ToastIcon = React.forwardRef<
	React.ElementRef<typeof ToastPrimitives.Root>,
	React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> &
		VariantProps<typeof toastVariants>
>(({ className, variant = "success" }) => {
	if (variant === "success") {
		return (
			<SuccessIcon className={clsx(className, "text-feedback-positive-900")} />
		);
	}

	if (variant === "warning") {
		return (
			<ErrorIcon className={clsx(className, "text-feedback-attention-900")} />
		);
	}

	if (variant === "error") {
		return (
			<ErrorIcon className={clsx(className, "text-feedback-negative-900")} />
		);
	}

	if (variant === "info") {
		return <InfoIcon className={clsx(className, "text-feedback-info-900")} />;
	}
});

const Toast = React.forwardRef<
	React.ElementRef<typeof ToastPrimitives.Root>,
	React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> &
		VariantProps<typeof toastVariants>
>(({ className, variant, ...props }, ref) => {
	return (
		<ToastPrimitives.Root
			ref={ref}
			className={cn(toastVariants({ variant }), className)}
			{...props}
		/>
	);
});
Toast.displayName = ToastPrimitives.Root.displayName;

const ToastCopy = ({
	text,
	href,
	toastAction = () => {
		if (href) {
			navigator.clipboard.writeText(href);
		}
	},
}: {
	text: string;
	href?: string;
	toastAction?: () => void;
}) => (
	<button
		onClick={toastAction}
		type="button"
		className="flex flex-row gap-2 group mb-2"
	>
		<div className="flex flex-col items-center justify-center size-6 bg-[#888787] rounded-full">
			<CopyIcon className="size-[10px]" />
		</div>
		<span className="text-[#888787] hover:text-white  ease-in-out duration-100  text-base font-medium font-['Articulat CF'] leading-normal">
			{text}
		</span>
	</button>
);

const ToastAction = React.forwardRef<
	React.ElementRef<typeof ToastPrimitives.Action>,
	React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>
>(({ className, ...props }, ref) => (
	<ToastPrimitives.Action
		ref={ref}
		className={cn(
			"inline-flex h-8  shrink-0 items-center justify-center rounded-md border border-neutral-200 bg-transparent px-3 text-sm font-medium transition-colors hover:bg-neutral-100 focus:outline-none focus:ring-1 focus:ring-neutral-950 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-neutral-100/40 group-[.destructive]:hover:border-red-500/30 group-[.destructive]:hover:bg-red-500 group-[.destructive]:hover:text-neutral-50 group-[.destructive]:focus:ring-red-500 dark:border-neutral-800 dark:hover:bg-neutral-800 dark:focus:ring-neutral-300 dark:group-[.destructive]:border-neutral-800/40 dark:group-[.destructive]:hover:border-red-900/30 dark:group-[.destructive]:hover:bg-red-900 dark:group-[.destructive]:hover:text-neutral-50 dark:group-[.destructive]:focus:ring-red-900",
			className,
		)}
		{...props}
	/>
));
ToastAction.displayName = ToastPrimitives.Action.displayName;

const ToastClose = React.forwardRef<
	React.ElementRef<typeof ToastPrimitives.Close>,
	React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>
>(({ className, ...props }, ref) => (
	<ToastPrimitives.Close
		ref={ref}
		className={cn("my-auto mx-0 rounded-md cursor-pointer", className)}
		toast-close=""
		{...props}
	>
		<Close className="size-5 text-[#C0C0C0]" />
	</ToastPrimitives.Close>
));
ToastClose.displayName = ToastPrimitives.Close.displayName;

const ToastTitle = React.forwardRef<
	React.ElementRef<typeof ToastPrimitives.Title>,
	React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
>(({ className, ...props }, ref) => (
	<ToastPrimitives.Title
		ref={ref}
		className={cn(
			"text-text-light-900 text-[18px] leading-[120%] sm:text-lg font-medium font-articulat leading-normal [&+div]:text-xs",
			className,
		)}
		{...props}
	/>
));
ToastTitle.displayName = ToastPrimitives.Title.displayName;

const ToastDescription = React.forwardRef<
	React.ElementRef<typeof ToastPrimitives.Description>,
	React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>
>(({ className, ...props }, ref) => (
	<ToastPrimitives.Description
		ref={ref}
		className={cn(
			"text-text-light-500 text-[14px] font-medium font-articulat leading-normal mb-2",
			className,
		)}
		{...props}
	/>
));

const ToastTimeline = ({
	duration,
	isPaused,
	variant,
}: {
	duration: number;
	isPaused: boolean;
	variant?: "error" | "success" | "warning" | "info" | null;
}) => {
	return (
		<div>
			<div
				className={cn(
					"absolute bottom-2 left-4 h-[3px] w-[90%] rounded bg-fill-100",
				)}
			/>

			<div
				data-variant={variant}
				className={cn(
					"absolute bottom-2 left-4 h-[3px] w-[90%] data-[variant=error]:bg-feedback-negative-900 rounded data-[variant=success]:bg-feedback-positive-900  data-[variant=warning]:bg-feedback-attention-900 data-[variant=info]:bg-feedback-info-900 toast-progress-animation",
				)}
				style={{
					animationDuration: `${duration}ms`,
					animationPlayState: isPaused ? "paused" : "running",
				}}
			/>
		</div>
	);
};

ToastDescription.displayName = ToastPrimitives.Description.displayName;

type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>;

type ToastActionElement = React.ReactElement<typeof ToastAction>;

function Toaster() {
	const { toasts, isPaused, setIsPaused } = useToast();

	React.useEffect(() => {
		const handleFocus = () => {
			setIsPaused(false);
		};

		const handleBlur = () => {
			setIsPaused(true);
		};

		window.addEventListener("focus", handleFocus);
		window.addEventListener("blur", handleBlur);

		return () => {
			window.removeEventListener("focus", handleFocus);
			window.removeEventListener("blur", handleBlur);
		};
	}, [setIsPaused]);

	return (
		<ToastProvider>
			{toasts.map(
				({
					id,
					title,
					description,
					action,
					copy,
					href,
					toastAction,
					duration = 5000,
					withTimeline,
					...props
				}) => (
					<Toast
						key={id}
						duration={duration}
						{...props}
						onMouseEnter={() => setIsPaused(true)}
						onMouseLeave={() => setIsPaused(false)}
					>
						<ToastIcon className="size-12 mr-4" variant={props.variant} />
						<div className="grid gap-2 w-full">
							<div className="flex items-center w-full justify-between">
								{title && <ToastTitle>{title}</ToastTitle>} <ToastClose />
							</div>

							{description && (
								<ToastDescription>{description}</ToastDescription>
							)}

							{copy && (
								<ToastCopy text={copy} href={href} toastAction={toastAction} />
							)}
						</div>
						{action}

						{withTimeline && (
							<ToastTimeline
								duration={duration}
								isPaused={isPaused}
								variant={props.variant}
							/>
						)}
					</Toast>
				),
			)}
			<ToastViewport />
		</ToastProvider>
	);
}

const TOASTER_DESCRIPTION_PATTERNS = {
	errorPattern: (
		<div>
			<span>
				<p>Please try again later</p>
				<p className="mt-2">
					If the problem persists, copy the error message below and contact our
					support team
				</p>
			</span>

			<div className="space-x-4 flex">
				<TextLink className="flex items-center gap-1">
					<Copy className="text-feedback-info-900" width={15} height={12} />[
					Error code ]
				</TextLink>

				<TextLink className="flex items-center gap-1" href={LINKS.discord}>
					<Discord className="text-feedback-info-900" width={15} height={12} />[
					Support ]
				</TextLink>
			</div>
		</div>
	),
};

export {
	type ToastProps,
	type ToastActionElement,
	ToastProvider,
	ToastViewport,
	Toast,
	ToastTitle,
	ToastDescription,
	ToastClose,
	ToastAction,
	ToastIcon,
	ToastCopy,
	ToastTimeline,
	Toaster,
	TOASTER_DESCRIPTION_PATTERNS,
};
