/**
 * Notification Store 单元测试
 *
 * 覆盖：addNotification / removeNotification / clearAll / 自动过期清除
 */

import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { useNotificationStore } from "@/lib/stores/notification-store";

describe("useNotificationStore", () => {
  beforeEach(() => {
    // 重置 store 到初始状态
    useNotificationStore.setState({ notifications: [] });
    vi.useFakeTimers();
  });

  afterEach(() => {
    vi.useRealTimers();
  });

  // ── addNotification ────────────────────────────────────────────────────

  describe("addNotification", () => {
    it("应添加一条通知到队列", () => {
      const { addNotification } = useNotificationStore.getState();
      const id = addNotification({ type: "success", message: "操作成功" });

      expect(id).toBeTruthy();
      expect(id).toMatch(/^notif-/);

      const { notifications } = useNotificationStore.getState();
      expect(notifications).toHaveLength(1);
      expect(notifications[0].type).toBe("success");
      expect(notifications[0].message).toBe("操作成功");
    });

    it("应支持不同类型的通知", () => {
      const { addNotification } = useNotificationStore.getState();

      addNotification({ type: "success", message: "成功" });
      addNotification({ type: "error", message: "错误" });
      addNotification({ type: "warning", message: "警告" });
      addNotification({ type: "info", message: "信息" });

      const { notifications } = useNotificationStore.getState();
      expect(notifications).toHaveLength(4);
      expect(notifications[0].type).toBe("success");
      expect(notifications[1].type).toBe("error");
      expect(notifications[2].type).toBe("warning");
      expect(notifications[3].type).toBe("info");
    });

    it("应支持可选标题", () => {
      const { addNotification } = useNotificationStore.getState();
      addNotification({ type: "info", message: "消息", title: "标题" });

      const { notifications } = useNotificationStore.getState();
      expect(notifications[0].title).toBe("标题");
    });

    it("默认过期时间应按类型自动设置", () => {
      const { addNotification } = useNotificationStore.getState();

      addNotification({ type: "success", message: "成功" });
      addNotification({ type: "error", message: "错误" });
      addNotification({ type: "warning", message: "警告" });
      addNotification({ type: "info", message: "信息" });

      const { notifications } = useNotificationStore.getState();
      expect(notifications[0].duration).toBe(3000); // success
      expect(notifications[1].duration).toBe(5000); // error
      expect(notifications[2].duration).toBe(4000); // warning
      expect(notifications[3].duration).toBe(3000); // info
    });

    it("应支持自定义过期时间", () => {
      const { addNotification } = useNotificationStore.getState();
      addNotification({ type: "success", message: "自定义", duration: 10000 });

      const { notifications } = useNotificationStore.getState();
      expect(notifications[0].duration).toBe(10000);
    });

    it("duration 为 undefined 时应使用默认过期时间", () => {
      const { addNotification } = useNotificationStore.getState();
      // 不传 duration，使用 error 类型的默认值 5000
      addNotification({ type: "error", message: "使用默认" });

      const { notifications } = useNotificationStore.getState();
      expect(notifications[0].duration).toBe(5000);
    });

    it("每条通知应有唯一 ID", () => {
      const { addNotification } = useNotificationStore.getState();
      const id1 = addNotification({ type: "info", message: "第一条" });
      const id2 = addNotification({ type: "info", message: "第二条" });

      expect(id1).not.toBe(id2);
    });
  });

  // ── removeNotification ─────────────────────────────────────────────────

  describe("removeNotification", () => {
    it("应移除指定 ID 的通知", () => {
      const { addNotification, removeNotification } =
        useNotificationStore.getState();

      const id1 = addNotification({ type: "success", message: "保留" });
      const id2 = addNotification({ type: "error", message: "移除" });

      removeNotification(id2);

      const { notifications } = useNotificationStore.getState();
      expect(notifications).toHaveLength(1);
      expect(notifications[0].id).toBe(id1);
    });

    it("移除不存在的 ID 不应报错", () => {
      const { addNotification, removeNotification } =
        useNotificationStore.getState();

      addNotification({ type: "info", message: "测试" });
      expect(() => removeNotification("non-existent")).not.toThrow();

      const { notifications } = useNotificationStore.getState();
      expect(notifications).toHaveLength(1);
    });

    it("移除通知时应清除其定时器", () => {
      const { addNotification, removeNotification } =
        useNotificationStore.getState();

      const id = addNotification({ type: "success", message: "提前移除" });
      removeNotification(id);

      // 快进超过默认过期时间，不应再触发移除（避免对空列表操作）
      vi.advanceTimersByTime(5000);

      const { notifications } = useNotificationStore.getState();
      expect(notifications).toHaveLength(0);
    });
  });

  // ── 自动过期清除 ───────────────────────────────────────────────────────

  describe("自动过期清除", () => {
    it("到达过期时间后应自动移除通知", () => {
      const { addNotification } = useNotificationStore.getState();
      addNotification({ type: "success", message: "3秒后过期" });

      // 快进 3 秒
      vi.advanceTimersByTime(3000);

      const { notifications } = useNotificationStore.getState();
      expect(notifications).toHaveLength(0);
    });

    it("不同类型通知在不同时间过期", () => {
      const { addNotification } = useNotificationStore.getState();
      addNotification({ type: "success", message: "3秒" });
      addNotification({ type: "error", message: "5秒" });

      // 快进 3 秒，success 应被清除
      vi.advanceTimersByTime(3000);
      expect(useNotificationStore.getState().notifications).toHaveLength(1);
      expect(useNotificationStore.getState().notifications[0].type).toBe(
        "error"
      );

      // 再快进 2 秒（共 5 秒），error 也应被清除
      vi.advanceTimersByTime(2000);
      expect(useNotificationStore.getState().notifications).toHaveLength(0);
    });

    it("自定义 duration=0 的通知不会自动过期", () => {
      const { addNotification } = useNotificationStore.getState();
      // duration=0 时 setTimeout(cb, 0) 会在下一个事件循环触发
      // 但 effectiveDuration !== null 为 true，所以会设置定时器
      // 这里测试 duration 传入 0 的行为
      addNotification({ type: "error", message: "0 毫秒过期", duration: 0 });

      // 0 毫秒定时器应立即触发
      vi.advanceTimersByTime(1);

      const { notifications } = useNotificationStore.getState();
      expect(notifications).toHaveLength(0);
    });

    it("自定义 duration 应在指定时间后过期", () => {
      const { addNotification } = useNotificationStore.getState();
      addNotification({ type: "info", message: "1秒过期", duration: 1000 });

      vi.advanceTimersByTime(999);
      expect(useNotificationStore.getState().notifications).toHaveLength(1);

      vi.advanceTimersByTime(1);
      expect(useNotificationStore.getState().notifications).toHaveLength(0);
    });
  });

  // ── clearAll ────────────────────────────────────────────────────────────

  describe("clearAll", () => {
    it("应清空所有通知", () => {
      const { addNotification } = useNotificationStore.getState();
      addNotification({ type: "success", message: "A" });
      addNotification({ type: "error", message: "B" });
      addNotification({ type: "warning", message: "C" });

      expect(useNotificationStore.getState().notifications).toHaveLength(3);

      const { clearAll } = useNotificationStore.getState();
      clearAll();

      expect(useNotificationStore.getState().notifications).toHaveLength(0);
    });

    it("clearAll 后定时器不应再触发", () => {
      const { addNotification } = useNotificationStore.getState();
      addNotification({ type: "success", message: "3秒后过期" });

      const { clearAll } = useNotificationStore.getState();
      clearAll();

      // 快进超过过期时间
      vi.advanceTimersByTime(5000);

      expect(useNotificationStore.getState().notifications).toHaveLength(0);
    });
  });
});
