import React, {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useRef,
  useState,
} from 'react';
import { AlertCircle, CheckCircle2, Info, X } from 'lucide-react';

export type AppDialogVariant = 'info' | 'success' | 'warning' | 'error';

interface AlertOptions {
  title?: string;
  variant?: AppDialogVariant;
  confirmLabel?: string;
}

interface ConfirmOptions extends AlertOptions {
  cancelLabel?: string;
}

interface DialogRequest {
  mode: 'alert' | 'confirm';
  message: string;
  title: string;
  variant: AppDialogVariant;
  confirmLabel: string;
  cancelLabel: string;
  resolve: (value: boolean) => void;
}

interface AppDialogContextValue {
  showAlert: (message: string, options?: AlertOptions) => Promise<void>;
  showConfirm: (message: string, options?: ConfirmOptions) => Promise<boolean>;
  showToast: (message: string, options?: { variant?: AppDialogVariant; duration?: number }) => void;
}

const AppDialogContext = createContext<AppDialogContextValue | null>(null);

const VARIANT_META: Record<
  AppDialogVariant,
  { icon: React.ReactNode; title: string; buttonClass: string }
> = {
  info: {
    icon: <Info className="w-5 h-5 text-indigo-500" />,
    title: '提示',
    buttonClass: 'bg-indigo-600 hover:bg-indigo-700 text-white',
  },
  success: {
    icon: <CheckCircle2 className="w-5 h-5 text-emerald-500" />,
    title: '成功',
    buttonClass: 'bg-emerald-600 hover:bg-emerald-700 text-white',
  },
  warning: {
    icon: <AlertCircle className="w-5 h-5 text-amber-500" />,
    title: '请注意',
    buttonClass: 'bg-amber-500 hover:bg-amber-600 text-white',
  },
  error: {
    icon: <AlertCircle className="w-5 h-5 text-rose-500" />,
    title: '出错了',
    buttonClass: 'bg-rose-600 hover:bg-rose-700 text-white',
  },
};

function AppDialogModal({
  dialog,
  onClose,
}: {
  dialog: DialogRequest;
  onClose: (confirmed: boolean) => void;
}) {
  const confirmBtnRef = useRef<HTMLButtonElement>(null);
  const meta = VARIANT_META[dialog.variant];

  useEffect(() => {
    confirmBtnRef.current?.focus();
  }, []);

  useEffect(() => {
    const onKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') {
        e.preventDefault();
        onClose(dialog.mode === 'alert');
      }
    };
    window.addEventListener('keydown', onKeyDown);
    return () => window.removeEventListener('keydown', onKeyDown);
  }, [dialog.mode, onClose]);

  return (
    <div
      className="fixed inset-0 z-[9500] flex items-center justify-center bg-slate-950/60 backdrop-blur-sm p-4"
      onClick={() => onClose(dialog.mode === 'alert')}
      role="presentation"
    >
      <div
        className="bg-white rounded-2xl shadow-2xl w-full max-w-md overflow-hidden"
        onClick={(e) => e.stopPropagation()}
        role="alertdialog"
        aria-modal="true"
        aria-labelledby="app-dialog-title"
        aria-describedby="app-dialog-message"
      >
        <div className="flex items-start gap-3 px-5 py-4 border-b border-gray-100">
          <span className="shrink-0 mt-0.5">{meta.icon}</span>
          <div className="flex-1 min-w-0 pr-2">
            <h3 id="app-dialog-title" className="text-sm font-bold text-gray-900">
              {dialog.title}
            </h3>
          </div>
          <button
            type="button"
            onClick={() => onClose(dialog.mode === 'alert')}
            className="p-1.5 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-lg transition cursor-pointer shrink-0"
            aria-label="关闭"
          >
            <X className="w-4 h-4" />
          </button>
        </div>
        <div className="px-5 py-4">
          <p id="app-dialog-message" className="text-sm text-gray-600 leading-relaxed whitespace-pre-wrap">
            {dialog.message}
          </p>
        </div>
        <div className="flex justify-end gap-2 px-5 py-4 border-t border-gray-100 bg-gray-50/80">
          {dialog.mode === 'confirm' && (
            <button
              type="button"
              onClick={() => onClose(false)}
              className="px-4 py-2 border border-gray-200 text-gray-600 hover:bg-white rounded-lg text-sm font-medium cursor-pointer"
            >
              {dialog.cancelLabel}
            </button>
          )}
          <button
            ref={confirmBtnRef}
            type="button"
            onClick={() => onClose(true)}
            className={`px-4 py-2 rounded-lg text-sm font-semibold cursor-pointer ${meta.buttonClass}`}
          >
            {dialog.confirmLabel}
          </button>
        </div>
      </div>
    </div>
  );
}

function AppToast({
  message,
  variant = 'success',
  onDismiss,
}: {
  message: string;
  variant: AppDialogVariant;
  onDismiss: () => void;
}) {
  const meta = VARIANT_META[variant];

  useEffect(() => {
    const timer = window.setTimeout(onDismiss, 2000);
    return () => window.clearTimeout(timer);
  }, [onDismiss]);

  return (
    <div
      className="fixed left-1/2 bottom-[max(1.25rem,env(safe-area-inset-bottom))] z-[10001] -translate-x-1/2 pointer-events-none"
      role="status"
      aria-live="polite"
    >
      <div className="flex items-center gap-2 px-4 py-2.5 rounded-xl shadow-lg border border-black/10 bg-[#2a2a2a] text-[#f0f0f0] text-[12px] font-medium max-w-[min(90vw,20rem)]">
        <span className="shrink-0">{meta.icon}</span>
        <span className="truncate">{message}</span>
      </div>
    </div>
  );
}

export function AppDialogProvider({ children }: { children: React.ReactNode }) {
  const [dialog, setDialog] = useState<DialogRequest | null>(null);
  const [toast, setToast] = useState<{ message: string; variant: AppDialogVariant } | null>(null);
  const toastTimerRef = useRef<number | null>(null);

  const showAlert = useCallback((message: string, options?: AlertOptions) => {
    const variant = options?.variant ?? 'info';
    return new Promise<void>((resolve) => {
      setDialog({
        mode: 'alert',
        message,
        title: options?.title ?? VARIANT_META[variant].title,
        variant,
        confirmLabel: options?.confirmLabel ?? '知道了',
        cancelLabel: '',
        resolve: () => resolve(),
      });
    });
  }, []);

  const showConfirm = useCallback((message: string, options?: ConfirmOptions) => {
    const variant = options?.variant ?? 'warning';
    return new Promise<boolean>((resolve) => {
      setDialog({
        mode: 'confirm',
        message,
        title: options?.title ?? VARIANT_META[variant].title,
        variant,
        confirmLabel: options?.confirmLabel ?? '确定',
        cancelLabel: options?.cancelLabel ?? '取消',
        resolve,
      });
    });
  }, []);

  const dismissToast = useCallback(() => {
    if (toastTimerRef.current !== null) {
      window.clearTimeout(toastTimerRef.current);
      toastTimerRef.current = null;
    }
    setToast(null);
  }, []);

  const showToast = useCallback(
    (message: string, options?: { variant?: AppDialogVariant; duration?: number }) => {
      dismissToast();
      const variant = options?.variant ?? 'success';
      setToast({ message, variant });
      const duration = options?.duration ?? 2000;
      toastTimerRef.current = window.setTimeout(() => {
        toastTimerRef.current = null;
        setToast(null);
      }, duration);
    },
    [dismissToast]
  );

  const closeDialog = useCallback((confirmed: boolean) => {
    setDialog((current) => {
      current?.resolve(confirmed);
      return null;
    });
  }, []);

  return (
    <AppDialogContext.Provider value={{ showAlert, showConfirm, showToast }}>
      {children}
      {dialog && <AppDialogModal dialog={dialog} onClose={closeDialog} />}
      {toast && (
        <AppToast message={toast.message} variant={toast.variant} onDismiss={dismissToast} />
      )}
    </AppDialogContext.Provider>
  );
}

export function useAppDialog() {
  const ctx = useContext(AppDialogContext);
  if (!ctx) {
    throw new Error('useAppDialog must be used within AppDialogProvider');
  }
  return ctx;
}
