'use client';
import React, { createContext, useCallback, useContext, useEffect, useRef, useState } from 'react';
import { clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';

/* ---------- Types ---------- */

export type ToastVariant = 'success' | 'error' | 'info' | 'loading';

export interface ToastItem {
  id: string;
  variant: ToastVariant;
  message: string;
  duration?: number; // ms — 0 = manual dismiss
}

export interface ToastAPI {
  toast: (variant: ToastVariant, message: string, duration?: number) => string;
  dismiss: (id: string) => void;
  dismissAll: () => void;
}

/* ---------- Context ---------- */

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

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

/* ---------- Icons ---------- */

const CheckIcon: React.FC = () => (
  <svg className="h-5 w-5 text-emerald-400 shrink-0" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor">
    <path strokeLinecap="round" strokeLinejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
  </svg>
);

const ErrorIcon: React.FC = () => (
  <svg className="h-5 w-5 text-red-400 shrink-0" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor">
    <path strokeLinecap="round" strokeLinejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" />
  </svg>
);

const InfoIcon: React.FC = () => (
  <svg className="h-5 w-5 text-blue-400 shrink-0" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor">
    <path strokeLinecap="round" strokeLinejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" />
  </svg>
);

const LoadingIcon: React.FC = () => (
  <svg className="h-5 w-5 text-gray-400 animate-spin shrink-0" fill="none" viewBox="0 0 24 24">
    <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
    <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
  </svg>
);

const icons: Record<ToastVariant, React.FC> = {
  success: CheckIcon,
  error: ErrorIcon,
  info: InfoIcon,
  loading: LoadingIcon,
};

const borderColors: Record<ToastVariant, string> = {
  success: 'border-l-emerald-500',
  error: 'border-l-red-500',
  info: 'border-l-blue-500',
  loading: 'border-l-gray-500',
};

const defaultDurations: Record<ToastVariant, number> = {
  success: 5000,
  error: 8000,
  info: 5000,
  loading: 0, // manual dismiss
};

/* ---------- Single Toast ---------- */

interface ToastCardProps {
  item: ToastItem;
  onDismiss: (id: string) => void;
  className?: string;
}

const ToastCard: React.FC<ToastCardProps> = ({ item, onDismiss, className }) => {
  const [exiting, setExiting] = useState(false);
  const timerRef = useRef<ReturnType<typeof setTimeout>>(undefined);
  const Icon = icons[item.variant];
  const duration = item.duration ?? defaultDurations[item.variant];

  useEffect(() => {
    if (duration > 0) {
      timerRef.current = setTimeout(() => {
        setExiting(true);
        setTimeout(() => onDismiss(item.id), 200);
      }, duration);
    }
    return () => clearTimeout(timerRef.current);
  }, [duration, item.id, onDismiss]);

  return (
    <div
      role="alert"
      className={twMerge(
        clsx(
          'flex items-start gap-3 px-4 py-3 rounded-lg border-l-4',
          'bg-gray-900 border border-gray-700 shadow-lg shadow-black/30',
          'transition-all duration-200 ease-out',
          borderColors[item.variant],
          exiting
            ? 'opacity-0 translate-x-4'
            : 'opacity-100 translate-x-0 animate-[slideInRight_0.25s_ease-out]',
        ),
        className,
      )}
    >
      <Icon />
      <p className="text-sm text-gray-200 flex-1 pt-0.5">{item.message}</p>
      <button
        onClick={() => {
          setExiting(true);
          setTimeout(() => onDismiss(item.id), 200);
        }}
        className="text-gray-500 hover:text-gray-300 transition-colors shrink-0 pt-0.5"
        aria-label="Dismiss"
      >
        <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor">
          <path strokeLinecap="round" strokeLinejoin="round" d="M6 18 18 6M6 6l12 12" />
        </svg>
      </button>
    </div>
  );
};

/* ---------- Provider ---------- */

export interface ToastProviderProps {
  children: React.ReactNode;
  className?: string;
}

let globalId = 0;

export const ToastProvider: React.FC<ToastProviderProps> = ({ children, className }) => {
  const [toasts, setToasts] = useState<ToastItem[]>([]);

  const dismiss = useCallback((id: string) => {
    setToasts((prev) => prev.filter((t) => t.id !== id));
  }, []);

  const dismissAll = useCallback(() => setToasts([]), []);

  const toast = useCallback(
    (variant: ToastVariant, message: string, duration?: number): string => {
      const id = `toast-${++globalId}`;
      setToasts((prev) => [...prev, { id, variant, message, duration }]);
      return id;
    },
    [],
  );

  return (
    <ToastContext.Provider value={{ toast, dismiss, dismissAll }}>
      {children}

      {/* Toast container — bottom-right */}
      <div
        className={twMerge(
          'fixed bottom-4 right-4 z-50 flex flex-col gap-2 w-96 max-w-[calc(100vw-2rem)]',
          className,
        )}
        aria-live="polite"
      >
        {toasts.map((t) => (
          <ToastCard key={t.id} item={t} onDismiss={dismiss} />
        ))}
      </div>
    </ToastContext.Provider>
  );
};

ToastProvider.displayName = 'ToastProvider';
