import React, {
  useCallback,
  useMemo,
  useRef,
  useState,
} from "react";
import { CheckCircle2, Info, AlertTriangle, X, XCircle } from "lucide-react";
import { ToastContext, type ToastOptions, type ToastContextValue } from "./ToastContext";

/** ===================== 可调默认项 ===================== */
const DEFAULT_DURATION = 4500;             // 默认显示时长（毫秒）
const ERROR_DURATION = 6000;               // 错误类默认更久
const EXTEND_ON_DUP_MS = 1000;             // 合并重复时延长的时间（毫秒）
const PREVENT_DUPLICATES = true;           // 开启自动去重与合并计数
const HOVER_PAUSES_DISMISS = true;         // 悬停暂停自动关闭
/** ===================================================== */

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

type ToastItem = Required<
  Omit<ToastOptions, "id" | "mergeKey">
> & {
  id: string;
  mergeKey: string;
  createdAt: number;
  startedAt: number;     // 本轮计时开始时间（用于计算剩余）
  remainingMs: number;   // 剩余时间（暂停时更新）
  paused: boolean;
  count: number;         // 合并计数
};

// useToast hook is now exported from ./useToast.ts for Fast Refresh compatibility

const variantStyle: Record<ToastVariant, string> = {
  success: "bg-emerald-600 border-emerald-500",
  error: "bg-red-600 border-red-500",
  warning: "bg-amber-600 border-amber-500",
  info: "bg-sky-600 border-sky-500",
};

const variantIcon: Record<ToastVariant, React.ReactNode> = {
  success: <CheckCircle2 className="w-5 h-5" />,
  error: <XCircle className="w-5 h-5" />,
  warning: <AlertTriangle className="w-5 h-5" />,
  info: <Info className="w-5 h-5" />,
};

export const ToastProvider: React.FC<React.PropsWithChildren> = ({ children }) => {
  const [toasts, setToasts] = useState<ToastItem[]>([]);
  // 保存每条 toast 的定时器句柄，避免放进 state
  const timers = useRef(new Map<string, number>());

  const removeTimer = (id: string) => {
    const t = timers.current.get(id);
    if (t) {
      window.clearTimeout(t);
      timers.current.delete(id);
    }
  };

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

  const schedule = (id: string, ms: number) => {
    if (ms <= 0) return; // 0 表示不自动关闭
    removeTimer(id);
    const h = window.setTimeout(() => {
      remove(id);
    }, ms);
    timers.current.set(id, h);
  };

  const now = () => Date.now();

  const makeMergeKey = (opts: ToastOptions) =>
    (opts.mergeKey ??
      `${opts.variant ?? "info"}|${opts.title ?? ""}|${opts.description ?? ""}`).trim();

  const normalizedDuration = (variant?: ToastVariant, provided?: number) => {
    if (provided === 0) return 0;
    if (typeof provided === "number" && provided > 0) return provided;
    return variant === "error" ? ERROR_DURATION : DEFAULT_DURATION;
  };

  const show = useCallback((opts: ToastOptions) => {
    const variant = opts.variant ?? "info";
    const durationMs = normalizedDuration(variant, opts.durationMs);
    const id = opts.id ?? `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
    const mergeKey = makeMergeKey(opts);

    setToasts((prev) => {
      if (PREVENT_DUPLICATES) {
        // 先找是否已存在相同 mergeKey 的 toast
        const idx = prev.findIndex((t) => t.mergeKey === mergeKey);
        if (idx >= 0) {
          const existing = prev[idx];
          // 更新计数、时长（延长）、重新计时
          const extended = Math.max(
            existing.remainingMs, 
            durationMs > 0 ? durationMs : existing.remainingMs
          ) + EXTEND_ON_DUP_MS;

          const updated: ToastItem = {
            ...existing,
            count: existing.count + 1,
            paused: false,
            startedAt: now(),
            remainingMs: existing.durationMs === 0 ? 0 : extended,
            // 如果传入了更大的 durationMs，也可以更新基准 duration
            durationMs: existing.durationMs === 0 ? 0 : Math.max(existing.durationMs, durationMs),
          };

          // 重新调度
          if (updated.durationMs > 0) {
            removeTimer(existing.id);
            schedule(existing.id, extended);
          }

          const next = [...prev];
          next[idx] = updated;
          return next;
        }
      }

      const item: ToastItem = {
        id,
        mergeKey,
        variant,
        title: opts.title ?? "",
        description: opts.description ?? "",
        durationMs,
        createdAt: now(),
        startedAt: now(),
        remainingMs: durationMs,
        paused: false,
        count: 1,
      };

      // 新建 toast 的定时
      if (durationMs > 0) schedule(id, durationMs);
      return [...prev, item];
    });
  }, [remove]);

  const pause = (id: string) => {
    if (!HOVER_PAUSES_DISMISS) return;
    setToasts((prev) =>
      prev.map((t) => {
        if (t.id !== id || t.paused) return t;
        // 暂停时计算剩余时间并清计时器
        const elapsed = now() - t.startedAt;
        const remaining = Math.max(0, t.remainingMs - elapsed);
        removeTimer(id);
        return { ...t, paused: true, remainingMs: remaining };
      })
    );
  };

  const resume = (id: string) => {
    if (!HOVER_PAUSES_DISMISS) return;
    setToasts((prev) =>
      prev.map((t) => {
        if (t.id !== id || !t.paused) return t;
        const next = { ...t, paused: false, startedAt: now() };
        if (next.durationMs > 0 && next.remainingMs > 0) {
          schedule(id, next.remainingMs);
        }
        return next;
      })
    );
  };

  const api = useMemo<ToastContextValue>(
    () => ({
      show,
      success: (msg, opts) =>
        show({
          ...opts,
          variant: "success",
          title: opts?.title ?? "Success",
          description: msg,
        }),
      error: (msg, opts) =>
        show({
          ...opts,
          variant: "error",
          title: opts?.title ?? "Error",
          description: msg,
          durationMs: opts?.durationMs ?? ERROR_DURATION,
        }),
      warning: (msg, opts) =>
        show({
          ...opts,
          variant: "warning",
          title: opts?.title ?? "Warning",
          description: msg,
        }),
      info: (msg, opts) =>
        show({
          ...opts,
          variant: "info",
          title: opts?.title ?? "Info",
          description: msg,
        }),
      remove,
    }),
    [remove, show]
  );

  return (
    <ToastContext.Provider value={api}>
      {children}

      {/* 容器 - 响应式定位 */}
      <div className="fixed z-[200] top-4 sm:top-4 right-2 sm:right-4 left-2 sm:left-auto space-y-2 sm:space-y-3 max-w-sm sm:w-[calc(100vw-2rem)]">
        {toasts.map((t) => {
          const barEnabled = t.durationMs > 0 && t.remainingMs > 0;
          // 估算进度（简单：剩余 / 基准），暂停时保持不动
          const elapsed = t.paused ? 0 : Math.max(0, Date.now() - t.startedAt);
          const left = Math.max(0, t.remainingMs - elapsed);
          const pct = barEnabled ? Math.max(0, Math.min(1, left / Math.max(1, t.durationMs))) : 0;

          return (
            <div
              key={t.id}
              className={`border text-white rounded-lg shadow-lg p-2.5 sm:p-3 pt-3 sm:pt-3.5 flex items-start gap-2 sm:gap-3 relative ${variantStyle[t.variant]} animate-fadeIn`}
              role="status"
              onMouseEnter={() => pause(t.id)}
              onMouseLeave={() => resume(t.id)}
            >
              {/* 顶部进度条（可选、低调） */}
              {barEnabled && (
                <div
                  className="absolute left-0 top-0 h-1 bg-white/40 rounded-t-lg transition-[width] duration-200 ease-linear"
                  style={{ width: `${pct * 100}%` }}
                />
              )}

              <div className="mt-0.5 flex-shrink-0">{variantIcon[t.variant]}</div>

              <div className="flex-1 min-w-0">
                <div className="flex items-center gap-1.5 sm:gap-2">
                  {t.title && <div className="font-semibold text-sm sm:text-base">{t.title}</div>}
                  {t.count > 1 && (
                    <span className="text-[10px] sm:text-xs px-1 sm:px-1.5 py-[1px] sm:py-[2px] rounded bg-black/20 border border-white/20">
                      ×{t.count}
                    </span>
                  )}
                </div>
                {t.description && (
                  <div className="text-xs sm:text-sm opacity-90 break-words">{t.description}</div>
                )}
              </div>

              <button
                onClick={() => remove(t.id)}
                className="opacity-80 hover:opacity-100 transition mt-0.5 flex-shrink-0 p-1"
                aria-label="Close"
              >
                <X className="w-3.5 h-3.5 sm:w-4 sm:h-4" />
              </button>
            </div>
          );
        })}
      </div>
    </ToastContext.Provider>
  );
};