'use client';

import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from 'react';
import { createPortal } from 'react-dom';
import {
  ToastStack,
  type ToastMessages,
  type ToastViewportPosition,
} from '@/components/ui/shared/Toast';

const DEFAULT_DURATION_MS = 4000;

export type UseToastOptions = {
  successMs?: number;
  errorMs?: number;
  infoMs?: number;
  defaultMs?: number;
};

export type ToastContextValue = {
  error: string;
  success: string;
  info: string;
  defaultMessage: string;
  setError: (message: string) => void;
  setSuccess: (message: string) => void;
  setInfo: (message: string) => void;
  setDefaultMessage: (message: string) => void;
  showError: (message: string) => void;
  showSuccess: (message: string) => void;
  showInfo: (message: string) => void;
  showDefault: (message: string) => void;
  clear: () => void;
  messages: ToastMessages;
};

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

function useToastState(options: UseToastOptions = {}): ToastContextValue {
  const successMs = options.successMs ?? DEFAULT_DURATION_MS;
  const errorMs = options.errorMs ?? DEFAULT_DURATION_MS;
  const infoMs = options.infoMs ?? DEFAULT_DURATION_MS;
  const defaultMs = options.defaultMs ?? DEFAULT_DURATION_MS;

  const [error, setError] = useState('');
  const [success, setSuccess] = useState('');
  const [info, setInfo] = useState('');
  const [defaultMessage, setDefaultMessage] = useState('');

  useEffect(() => {
    if (!success) return;
    const id = setTimeout(() => setSuccess(''), successMs);
    return () => clearTimeout(id);
  }, [success, successMs]);

  useEffect(() => {
    if (!error) return;
    const id = setTimeout(() => setError(''), errorMs);
    return () => clearTimeout(id);
  }, [error, errorMs]);

  useEffect(() => {
    if (!info) return;
    const id = setTimeout(() => setInfo(''), infoMs);
    return () => clearTimeout(id);
  }, [info, infoMs]);

  useEffect(() => {
    if (!defaultMessage) return;
    const id = setTimeout(() => setDefaultMessage(''), defaultMs);
    return () => clearTimeout(id);
  }, [defaultMessage, defaultMs]);

  const clear = useCallback(() => {
    setError('');
    setSuccess('');
    setInfo('');
    setDefaultMessage('');
  }, []);

  const showError = useCallback((message: string) => {
    setSuccess('');
    setInfo('');
    setDefaultMessage('');
    setError(message);
  }, []);

  const showSuccess = useCallback((message: string) => {
    setError('');
    setInfo('');
    setDefaultMessage('');
    setSuccess(message);
  }, []);

  const showInfo = useCallback((message: string) => {
    setError('');
    setSuccess('');
    setDefaultMessage('');
    setInfo(message);
  }, []);

  const showDefault = useCallback((message: string) => {
    setError('');
    setSuccess('');
    setInfo('');
    setDefaultMessage(message);
  }, []);

  const messages: ToastMessages = useMemo(
    () => ({ error, success, info, default: defaultMessage }),
    [error, success, info, defaultMessage],
  );

  return useMemo(
    () => ({
      error,
      success,
      info,
      defaultMessage,
      setError,
      setSuccess,
      setInfo,
      setDefaultMessage,
      showError,
      showSuccess,
      showInfo,
      showDefault,
      clear,
      messages,
    }),
    [
      error,
      success,
      info,
      defaultMessage,
      showError,
      showSuccess,
      showInfo,
      showDefault,
      clear,
      messages,
    ],
  );
}

type ToastProviderProps = {
  children: ReactNode;
  /** Fixed viewport position. Default `bottom` — visible when scrolled and above dialogs. */
  position?: Exclude<ToastViewportPosition, 'inline'>;
};

function GlobalToastHost({
  messages,
  position,
}: {
  messages: ToastMessages;
  position: Exclude<ToastViewportPosition, 'inline'>;
}) {
  const hasMessage = Boolean(
    messages.error || messages.success || messages.info || messages.default,
  );

  if (!hasMessage) {
    return null;
  }

  const positionClass =
    position === 'bottom'
      ? 'fixed bottom-4 left-0 right-0 z-[100] px-4 pb-[max(1rem,env(safe-area-inset-bottom))] pointer-events-none'
      : 'fixed top-4 left-0 right-0 z-[100] px-4 pt-[max(1rem,env(safe-area-inset-top))] pointer-events-none';

  return createPortal(
    <div className={positionClass} aria-live="polite">
      <div className="pointer-events-auto mx-auto w-full max-w-md">
        <ToastStack {...messages} />
      </div>
    </div>,
    document.body,
  );
}

export function ToastProvider({ children, position = 'bottom' }: ToastProviderProps) {
  const toast = useToastState();
  const [mounted, setMounted] = useState(false);

  useEffect(() => {
    setMounted(true);
  }, []);

  return (
    <ToastContext.Provider value={toast}>
      {children}
      {mounted ? <GlobalToastHost messages={toast.messages} position={position} /> : null}
    </ToastContext.Provider>
  );
}

/** Global app toasts — requires `<ToastProvider>` ancestor (dashboard layout). */
export function useToast(): ToastContextValue {
  const context = useContext(ToastContext);
  if (!context) {
    throw new Error('useToast must be used within ToastProvider');
  }
  return context;
}
