import {
  createContext,
  useContext,
  createSignal,
  For,
  Show,
  onCleanup,
} from "solid-js";
import { cn } from "~/lib/utils";
import type { JSX } from "solid-js";

type ToastVariant = "success" | "error" | "warning" | "info";

interface Toast {
  id: string;
  message: string;
  variant: ToastVariant;
  duration: number;
}

interface ToastContextValue {
  toasts: () => Toast[];
  showToast: (
    message: string,
    variant?: ToastVariant,
    duration?: number,
  ) => string;
  dismissToast: (id: string) => void;
}

const ToastContext = createContext<ToastContextValue>();

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

export function ToastProvider(props: { children: JSX.Element }) {
  const [toasts, setToasts] = createSignal<Toast[]>([]);
  const timers = new Map<string, ReturnType<typeof setTimeout>>();

  const showToast = (
    message: string,
    variant: ToastVariant = "info",
    duration = 4000,
  ) => {
    const id =
      globalThis.crypto?.randomUUID?.() ??
      Math.random().toString(36).slice(2, 10);
    const toast: Toast = { id, message, variant, duration };
    setToasts((prev) => [...prev, toast]);
    if (duration > 0) {
      const timer = setTimeout(() => dismissToast(id), duration);
      timers.set(id, timer);
    }
    return id;
  };

  const dismissToast = (id: string) => {
    const timer = timers.get(id);
    if (timer) {
      clearTimeout(timer);
      timers.delete(id);
    }
    setToasts((prev) => prev.filter((t) => t.id !== id));
  };

  onCleanup(() => {
    for (const timer of timers.values()) {
      clearTimeout(timer);
    }
    timers.clear();
  });

  const value: ToastContextValue = {
    toasts,
    showToast,
    dismissToast,
  };

  return (
    <ToastContext.Provider value={value}>
      {props.children}
      <ToastContainer />
    </ToastContext.Provider>
  );
}

const variantStyles: Record<ToastVariant, string> = {
  success:
    "border-[var(--color-success)] bg-[var(--color-success-bg)] text-[var(--color-success)]",
  error:
    "border-[var(--color-error)] bg-[var(--color-error-bg)] text-[var(--color-error)]",
  warning:
    "border-[var(--color-warning)] bg-[var(--color-warning-bg)] text-[var(--color-warning)]",
  info: "border-[var(--color-info)] bg-[var(--color-info-bg)] text-[var(--color-info)]",
};

function ToastContainer() {
  const { toasts, dismissToast } = useToast();

  return (
    <Show when={toasts().length > 0}>
      <div
        class="fixed bottom-4 right-4 z-50 flex flex-col gap-2 max-w-sm"
        role="region"
        aria-label="Notifications"
      >
        <For each={toasts()}>
          {(toast) => (
            <div
              class={cn(
                "flex items-center justify-between gap-2 px-4 py-3 rounded-lg border-l-4 shadow-lg transition-all duration-200",
                variantStyles[toast.variant],
              )}
              role="alert"
            >
              <span class="text-sm font-medium">{toast.message}</span>
              <button
                type="button"
                onClick={() => dismissToast(toast.id)}
                class="shrink-0 text-current opacity-70 hover:opacity-100 transition-opacity cursor-pointer"
                aria-label="Dismiss"
              >
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  class="h-4 w-4"
                  viewBox="0 0 20 20"
                  fill="currentColor"
                >
                  <path
                    fill-rule="evenodd"
                    d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
                    clip-rule="evenodd"
                  />
                </svg>
              </button>
            </div>
          )}
        </For>
      </div>
    </Show>
  );
}
