"use client";

/**
 * Thông báo nhanh (toast) hiện ở góc màn hình sau mỗi thao tác — "Đã lưu", "Đã xoá", lỗi...
 * Đặt một ToastProvider ở layout; mọi thành phần con gọi `useToast()` để báo kết quả.
 */
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, type ReactNode } from "react";
import { usePathname } from "next/navigation";

type Tone = "success" | "error" | "info";
type ToastItem = { id: number; tone: Tone; message: string };

type ToastApi = {
  success: (message: string) => void;
  error: (message: string) => void;
  info: (message: string) => void;
};

// Ngoài Provider (trang đăng nhập...) thì không làm gì thay vì báo lỗi.
const NOOP: ToastApi = { success: () => {}, error: () => {}, info: () => {} };

const ToastContext = createContext<ToastApi>(NOOP);

export function useToast(): ToastApi {
  return useContext(ToastContext);
}

/**
 * Action kết thúc bằng redirect() làm form biến mất trước khi kịp báo kết quả. Nên lưu lời nhắn
 * tạm vào sessionStorage, ToastProvider (nằm ở layout, không bị gỡ) sẽ hiện nó khi sang trang mới.
 */
const FLASH_KEY = "crm-flash-toast";
export const flashToast = {
  set: (message: string) => {
    try {
      sessionStorage.setItem(FLASH_KEY, message);
    } catch {}
  },
  clear: () => {
    try {
      sessionStorage.removeItem(FLASH_KEY);
    } catch {}
  },
};

const DURATION_MS: Record<Tone, number> = { success: 3500, info: 4500, error: 7000 };
const MAX_VISIBLE = 4;

export function ToastProvider({ children }: { children: ReactNode }) {
  const [items, setItems] = useState<ToastItem[]>([]);
  const nextId = useRef(1);

  const dismiss = useCallback((id: number) => {
    setItems((current) => current.filter((item) => item.id !== id));
  }, []);

  const push = useCallback(
    (tone: Tone, message: string) => {
      const id = nextId.current++;
      setItems((current) => [...current, { id, tone, message }].slice(-MAX_VISIBLE));
      setTimeout(() => dismiss(id), DURATION_MS[tone]);
    },
    [dismiss],
  );

  const pathname = usePathname();
  useEffect(() => {
    try {
      const message = sessionStorage.getItem(FLASH_KEY);
      if (message) {
        sessionStorage.removeItem(FLASH_KEY);
        push("success", message);
      }
    } catch {}
  }, [pathname, push]);

  const api = useMemo<ToastApi>(
    () => ({
      success: (message) => push("success", message),
      error: (message) => push("error", message),
      info: (message) => push("info", message),
    }),
    [push],
  );

  return (
    <ToastContext.Provider value={api}>
      {children}
      <div
        className="pointer-events-none fixed inset-x-0 bottom-4 z-[60] flex flex-col items-center gap-2 px-4 sm:inset-x-auto sm:right-4 sm:top-4 sm:bottom-auto sm:items-end sm:px-0"
        aria-live="polite"
      >
        {items.map((item) => (
          <ToastCard key={item.id} item={item} onClose={() => dismiss(item.id)} />
        ))}
      </div>
    </ToastContext.Provider>
  );
}

const TONE_STYLE: Record<Tone, { box: string; icon: string; glyph: string }> = {
  success: { box: "border-emerald-200 bg-white", icon: "bg-emerald-50 text-emerald-700", glyph: "✓" },
  error: { box: "border-red-200 bg-white", icon: "bg-red-50 text-red-700", glyph: "!" },
  info: { box: "border-[var(--color-line)] bg-white", icon: "bg-ink-100 text-ink-500", glyph: "i" },
};

function ToastCard({ item, onClose }: { item: ToastItem; onClose: () => void }) {
  const style = TONE_STYLE[item.tone];
  return (
    <div
      role={item.tone === "error" ? "alert" : "status"}
      className={`toast-in pointer-events-auto flex w-full max-w-sm items-start gap-3 rounded-xl border px-3.5 py-3 shadow-lg ${style.box}`}
    >
      <span
        aria-hidden
        className={`mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full text-xs font-bold ${style.icon}`}
      >
        {style.glyph}
      </span>
      <p className="min-w-0 flex-1 text-sm font-medium text-ink-700">{item.message}</p>
      <button
        type="button"
        onClick={onClose}
        aria-label="Đóng thông báo"
        className="-mr-1 shrink-0 rounded px-1 text-lg leading-none text-ink-300 hover:text-ink-500"
      >
        ×
      </button>
    </div>
  );
}
