import React, {
	createContext,
	useContext,
	useState,
	useCallback,
	useRef,
	useEffect,
} from "react";

export type ToastSeverity = "info" | "success" | "warning" | "error";

export interface ToastItem {
	id: string;
	message: string;
	severity: ToastSeverity;
	duration: number | null;
	createdAt: number;
}

interface ToastContextValue {
	toasts: ToastItem[];
	addToast: (
		message: string,
		severity: ToastSeverity,
		duration?: number | null,
	) => void;
	removeToast: (id: string) => void;
}

const ToastContext = createContext<ToastContextValue | null>(null);

let globalToastId = 0;

export function ToastProvider({ children }: { children: React.ReactNode }) {
	const [toasts, setToasts] = useState<ToastItem[]>([]);
	const timersRef = useRef<Map<string, ReturnType<typeof setTimeout>>>(
		new Map(),
	);

	const removeToast = useCallback((id: string) => {
		setToasts((prev) => prev.filter((t) => t.id !== id));
		const timer = timersRef.current.get(id);
		if (timer) {
			clearTimeout(timer);
			timersRef.current.delete(id);
		}
	}, []);

	const addToast = useCallback(
		(
			message: string,
			severity: ToastSeverity,
			duration: number | null = 3000,
		) => {
			const id = `toast-${++globalToastId}`;
			const toast: ToastItem = {
				id,
				message,
				severity,
				duration,
				createdAt: Date.now(),
			};
			setToasts((prev) => [...prev, toast]);

			if (duration !== null && duration > 0) {
				const timer = setTimeout(() => {
					removeToast(id);
				}, duration);
				timersRef.current.set(id, timer);
			}
		},
		[removeToast],
	);

	useEffect(() => {
		toast.info = (msg, opts) => addToast(msg, "info", opts?.duration ?? 3000);
		toast.success = (msg, opts) =>
			addToast(msg, "success", opts?.duration ?? 3000);
		toast.warning = (msg, opts) =>
			addToast(msg, "warning", opts?.duration ?? 5000);
		toast.error = (msg, opts) =>
			addToast(msg, "error", opts?.duration ?? 10000);
		return () => {
			toast.info = () => {};
			toast.success = () => {};
			toast.warning = () => {};
			toast.error = () => {};
		};
	}, [addToast]);

	return (
		<ToastContext.Provider value={{ toasts, addToast, removeToast }}>
			{children}
			<ToastContainer toasts={toasts} onDismiss={removeToast} />
		</ToastContext.Provider>
	);
}

export function useToast() {
	const ctx = useContext(ToastContext);
	if (!ctx) {
		throw new Error("useToast must be used within ToastProvider");
	}
	return ctx;
}

type ToastFn = (message: string, opts?: { duration?: number }) => void;

export const toast: {
	info: ToastFn;
	success: ToastFn;
	warning: ToastFn;
	error: ToastFn;
} = {
	info: () => {
		/* assigned by ToastProvider */
	},
	success: () => {
		/* assigned by ToastProvider */
	},
	warning: () => {
		/* assigned by ToastProvider */
	},
	error: () => {
		/* assigned by ToastProvider */
	},
};

function severityStyles(severity: ToastSeverity): React.CSSProperties {
	switch (severity) {
		case "success":
			return { backgroundColor: "#16a34a", color: "#fff" };
		case "warning":
			return { backgroundColor: "#d97706", color: "#fff" };
		case "error":
			return { backgroundColor: "#dc2626", color: "#fff" };
		case "info":
		default:
			return { backgroundColor: "#2563eb", color: "#fff" };
	}
}

function ToastContainer({
	toasts,
	onDismiss,
}: {
	toasts: ToastItem[];
	onDismiss: (id: string) => void;
}) {
	return (
		<div
			style={{
				position: "fixed",
				top: 16,
				right: 16,
				zIndex: 9999,
				display: "flex",
				flexDirection: "column",
				gap: 8,
				maxWidth: 360,
				width: "100%",
				pointerEvents: "none",
			}}
		>
			{toasts.map((t) => (
				<div
					key={t.id}
					style={{
						pointerEvents: "auto",
						padding: "12px 16px",
						borderRadius: 8,
						boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
						display: "flex",
						alignItems: "center",
						justifyContent: "space-between",
						gap: 12,
						animation: "toastSlideIn 0.3s ease-out",
						...severityStyles(t.severity),
					}}
				>
					<span style={{ fontSize: 14, fontWeight: 500, lineHeight: 1.4 }}>
						{t.message}
					</span>
					<button
						onClick={() => onDismiss(t.id)}
						style={{
							background: "none",
							border: "none",
							color: "inherit",
							cursor: "pointer",
							fontSize: 18,
							lineHeight: 1,
							padding: 0,
							margin: 0,
							opacity: 0.8,
						}}
						aria-label="Dismiss toast"
						type="button"
					>
						×
					</button>
				</div>
			))}
		</div>
	);
}
