// Tests for downloads store
// TRACES: UR-011, UR-013, UR-018 | DR-015, DR-017 | UT-010, UT-024
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { get } from "svelte/store";

// Mock Tauri APIs
const mockInvoke = vi.fn();
const mockListen = vi.fn();

vi.mock("@tauri-apps/api/core", () => ({
  invoke: mockInvoke,
}));

vi.mock("@tauri-apps/api/event", () => ({
  listen: mockListen,
}));

describe("downloads store", () => {
  let eventHandler: ((event: { payload: unknown }) => void) | null = null;

  beforeEach(() => {
    vi.clearAllMocks();
    // Reset the invoke mock to clear any remaining queued return values
    mockInvoke.mockReset();

    // Capture the event handler when listen is called
    mockListen.mockImplementation((_event: string, handler: (event: { payload: unknown }) => void) => {
      eventHandler = handler;
      return Promise.resolve(() => {});
    });
  });

  afterEach(async () => {
    // Clean up event listeners
    const { cleanupDownloadEvents } = await import("./downloads");
    cleanupDownloadEvents();
    eventHandler = null;

    // Clear all mocks
    vi.clearAllMocks();
    mockInvoke.mockReset();
    mockListen.mockReset();
  });

  describe("initial state", () => {
    it("should have empty downloads initially", async () => {
      const { downloads } = await import("./downloads");
      const state = get(downloads);

      expect(state.downloads).toEqual({});
      expect(state.stats.activeCount).toBe(0);
      expect(state.stats.queuedCount).toBe(0);
    });
  });

  describe("downloadItem", () => {
    it("should call invoke with correct parameters", async () => {
      const { downloads } = await import("./downloads");

      mockInvoke
        .mockResolvedValueOnce(123) // download_item returns ID
        .mockResolvedValueOnce({
          downloads: [],
          stats: {
            total: 0,
            activeCount: 0,
            queuedCount: 0,
            completedCount: 0,
            failedCount: 0,
            pausedCount: 0,
          },
        }); // get_downloads returns empty

      const downloadId = await downloads.downloadItem(
        "item-1",
        "user-1",
        "/path/to/file.mp3",
        "audio/mpeg",
        10
      );

      expect(mockInvoke).toHaveBeenCalledWith("download_item", {
        request: {
          itemId: "item-1",
          userId: "user-1",
          filePath: "/path/to/file.mp3",
          mimeType: "audio/mpeg",
          priority: 10,
          itemName: null,
          artistName: null,
          albumName: null,
          expectedSize: null,
        },
      });
      expect(downloadId).toBe(123);
    });

    it("should refresh downloads after queuing", async () => {
      const { downloads } = await import("./downloads");

      mockInvoke
        .mockResolvedValueOnce(123)
        .mockResolvedValueOnce({
          downloads: [
            {
              id: 123,
              itemId: "item-1",
              userId: "user-1",
              filePath: "/path/to/file.mp3",
              status: "pending",
              progress: 0,
              bytesDownloaded: 0,
              queuedAt: "2024-01-01T00:00:00Z",
              retryCount: 0,
              priority: 10,
              mediaType: "audio",
              downloadSource: "user",
            },
          ],
          stats: {
            total: 1,
            activeCount: 0,
            queuedCount: 1,
            completedCount: 0,
            failedCount: 0,
            pausedCount: 0,
          },
        });

      await downloads.downloadItem("item-1", "user-1", "/path/to/file.mp3");

      expect(mockInvoke).toHaveBeenCalledWith("get_downloads", {
        userId: "user-1",
        statusFilter: null,
      });

      const state = get(downloads);
      expect(state.downloads[123]).toBeDefined();
      expect(state.stats.queuedCount).toBe(1);
    });
  });

  describe("downloadAlbum", () => {
    it("should call invoke with correct parameters", async () => {
      const { downloads } = await import("./downloads");

      mockInvoke
        .mockResolvedValueOnce([1, 2, 3]) // download_album returns IDs
        .mockResolvedValueOnce({
          downloads: [],
          stats: {
            total: 0,
            activeCount: 0,
            queuedCount: 0,
            completedCount: 0,
            failedCount: 0,
            pausedCount: 0,
          },
        }); // get_downloads

      const ids = await downloads.downloadAlbum("album-1", "user-1", "/base/path");

      expect(mockInvoke).toHaveBeenCalledWith("download_album", {
        albumId: "album-1",
        userId: "user-1",
        basePath: "/base/path",
      });
      expect(ids).toEqual([1, 2, 3]);
    });
  });

  describe("pause/resume/cancel", () => {
    it("should call pause_download with correct ID", async () => {
      const { downloads } = await import("./downloads");
      mockInvoke.mockResolvedValueOnce(undefined);

      await downloads.pause(123);

      expect(mockInvoke).toHaveBeenCalledWith("pause_download", { downloadId: 123 });
    });

    it("should call resume_download with correct ID", async () => {
      const { downloads } = await import("./downloads");
      mockInvoke.mockResolvedValueOnce(undefined);

      await downloads.resume(123);

      expect(mockInvoke).toHaveBeenCalledWith("resume_download", { downloadId: 123 });
    });

    it("should call cancel_download with correct ID", async () => {
      const { downloads } = await import("./downloads");
      mockInvoke.mockResolvedValueOnce(undefined);

      await downloads.cancel(123);

      expect(mockInvoke).toHaveBeenCalledWith("cancel_download", { downloadId: 123 });
    });
  });

  describe("delete", () => {
    it("should call delete_download and remove from store", async () => {
      const { downloads } = await import("./downloads");

      // First add a download via refresh
      mockInvoke.mockResolvedValueOnce({
        downloads: [
          {
            id: 123,
            itemId: "item-1",
            userId: "user-1",
            filePath: "/path/to/file.mp3",
            status: "completed",
            progress: 1.0,
            bytesDownloaded: 1000,
            queuedAt: "2024-01-01T00:00:00Z",
            retryCount: 0,
            priority: 0,
            mediaType: "audio",
            downloadSource: "user",
          },
        ],
        stats: {
          total: 1,
          activeCount: 0,
          queuedCount: 0,
          completedCount: 1,
          failedCount: 0,
          pausedCount: 0,
        },
      });

      await downloads.refresh("user-1");
      expect(get(downloads).downloads[123]).toBeDefined();

      // Now delete
      mockInvoke.mockResolvedValueOnce(undefined);
      await downloads.delete(123);

      expect(mockInvoke).toHaveBeenCalledWith("delete_download", { downloadId: 123 });
      expect(get(downloads).downloads[123]).toBeUndefined();
    });
  });

  describe("refresh", () => {
    it("should update store with downloads from backend", async () => {
      const { downloads } = await import("./downloads");

      mockInvoke.mockResolvedValueOnce({
        downloads: [
          {
            id: 1,
            itemId: "item-1",
            userId: "user-1",
            filePath: "/path/1.mp3",
            status: "downloading",
            progress: 0.5,
            bytesDownloaded: 500,
            queuedAt: "2024-01-01T00:00:00Z",
            retryCount: 0,
            priority: 0,
            mediaType: "audio",
            downloadSource: "user",
          },
          {
            id: 2,
            itemId: "item-2",
            userId: "user-1",
            filePath: "/path/2.mp3",
            status: "pending",
            progress: 0,
            bytesDownloaded: 0,
            queuedAt: "2024-01-01T00:00:01Z",
            retryCount: 0,
            priority: 0,
            mediaType: "audio",
            downloadSource: "user",
          },
          {
            id: 3,
            itemId: "item-3",
            userId: "user-1",
            filePath: "/path/3.mp3",
            status: "completed",
            progress: 1.0,
            bytesDownloaded: 1000,
            queuedAt: "2024-01-01T00:00:02Z",
            retryCount: 0,
            priority: 0,
            mediaType: "audio",
            downloadSource: "user",
          },
        ],
        stats: {
          total: 3,
          activeCount: 1,
          queuedCount: 1,
          completedCount: 1,
          failedCount: 0,
          pausedCount: 0,
        },
      });

      await downloads.refresh("user-1");

      const state = get(downloads);
      expect(Object.keys(state.downloads).length).toBe(3);
      expect(state.stats.activeCount).toBe(1); // 1 downloading
      expect(state.stats.queuedCount).toBe(1); // 1 pending
    });

    // The Transfers view shows only in-flight rows; a completed transfer must
    // NOT appear there (it lives in Downloaded). Mirrors the /downloads page's
    // `transfers` derivation: active + pending + failed.
    // TRACES: UR-055 | DR-084 | UT-052
    it("transfers set excludes completed downloads", async () => {
      const { downloads, activeDownloads, pendingDownloads, failedDownloads } = await import(
        "./downloads"
      );

      mockInvoke.mockResolvedValueOnce({
        downloads: [
          { id: 1, itemId: "a", userId: "u", filePath: "/a", status: "downloading", progress: 0.5, bytesDownloaded: 5, queuedAt: "t", retryCount: 0, priority: 0, mediaType: "audio", downloadSource: "user" },
          { id: 2, itemId: "b", userId: "u", filePath: "/b", status: "pending", progress: 0, bytesDownloaded: 0, queuedAt: "t", retryCount: 0, priority: 0, mediaType: "audio", downloadSource: "user" },
          { id: 3, itemId: "c", userId: "u", filePath: "/c", status: "completed", progress: 1, bytesDownloaded: 9, queuedAt: "t", retryCount: 0, priority: 0, mediaType: "audio", downloadSource: "user" },
          { id: 4, itemId: "d", userId: "u", filePath: "/d", status: "failed", progress: 0, bytesDownloaded: 0, queuedAt: "t", retryCount: 1, priority: 0, mediaType: "audio", downloadSource: "user" },
        ],
        stats: { total: 4, activeCount: 1, queuedCount: 1, completedCount: 1, failedCount: 1, pausedCount: 0 },
      });

      await downloads.refresh("u");

      const transfers = get(activeDownloads)
        .concat(get(pendingDownloads))
        .concat(get(failedDownloads));
      const ids = transfers.map((d) => d.id).sort();
      expect(ids).toEqual([1, 2, 4]);
      expect(transfers.some((d) => d.status === "completed")).toBe(false);
    });

    it("should support status filter", async () => {
      const { downloads } = await import("./downloads");

      mockInvoke.mockResolvedValueOnce({
        downloads: [],
        stats: {
          total: 0,
          activeCount: 0,
          queuedCount: 0,
          completedCount: 0,
          failedCount: 0,
          pausedCount: 0,
        },
      });

      await downloads.refresh("user-1", ["pending", "downloading"]);

      expect(mockInvoke).toHaveBeenCalledWith("get_downloads", {
        userId: "user-1",
        statusFilter: ["pending", "downloading"],
      });
    });
  });

  describe("event handling", () => {
    it("should initialize event listener via initDownloadEvents", async () => {
      const { initDownloadEvents } = await import("./downloads");

      await initDownloadEvents();

      expect(mockListen).toHaveBeenCalledWith("download-event", expect.any(Function));
      expect(eventHandler).not.toBeNull();
    });

    it("should handle started event and refresh", async () => {
      const { downloads, initDownloadEvents } = await import("./downloads");

      // First add a pending download
      mockInvoke.mockResolvedValueOnce({
        downloads: [
          {
            id: 123,
            itemId: "item-1",
            userId: "user-1",
            filePath: "/path/to/file.mp3",
            status: "pending",
            progress: 0,
            bytesDownloaded: 0,
            queuedAt: "2024-01-01T00:00:00Z",
            retryCount: 0,
            priority: 0,
            mediaType: "audio",
            downloadSource: "user",
          },
        ],
        stats: {
          total: 1,
          activeCount: 0,
          queuedCount: 1,
          completedCount: 0,
          failedCount: 0,
          pausedCount: 0,
        },
      });

      await downloads.refresh("user-1");

      // Initialize event listener
      await initDownloadEvents();
      expect(eventHandler).not.toBeNull();

      // Mock refresh call that will happen when event is handled
      mockInvoke.mockResolvedValueOnce({
        downloads: [
          {
            id: 123,
            itemId: "item-1",
            userId: "user-1",
            filePath: "/path/to/file.mp3",
            status: "downloading",
            progress: 0,
            bytesDownloaded: 0,
            queuedAt: "2024-01-01T00:00:00Z",
            retryCount: 0,
            priority: 0,
            mediaType: "audio",
            downloadSource: "user",
          },
        ],
        stats: {
          total: 1,
          activeCount: 1,
          queuedCount: 0,
          completedCount: 0,
          failedCount: 0,
          pausedCount: 0,
        },
      });

      // Simulate started event
      eventHandler!({
        payload: {
          type: "started",
          downloadId: 123,
          itemId: "item-1",
        },
      });

      // Wait for async operations to complete
      await new Promise((resolve) => setTimeout(resolve, 100));

      const state = get(downloads);
      expect(state.downloads[123].status).toBe("downloading");
    });

    it("should handle completed event and refresh", async () => {
      const { downloads, initDownloadEvents } = await import("./downloads");

      mockInvoke.mockResolvedValueOnce({
        downloads: [
          {
            id: 123,
            itemId: "item-1",
            userId: "user-1",
            filePath: "/path/to/file.mp3",
            status: "downloading",
            progress: 0.99,
            bytesDownloaded: 990000,
            queuedAt: "2024-01-01T00:00:00Z",
            retryCount: 0,
            priority: 0,
            mediaType: "audio",
            downloadSource: "user",
          },
        ],
        stats: {
          total: 1,
          activeCount: 1,
          queuedCount: 0,
          completedCount: 0,
          failedCount: 0,
          pausedCount: 0,
        },
      });

      await downloads.refresh("user-1");

      // Initialize event listener
      await initDownloadEvents();

      // Mock the mark_download_completed invoke call
      mockInvoke.mockResolvedValueOnce(undefined);

      // Simulate completed event
      eventHandler!({
        payload: {
          type: "completed",
          downloadId: 123,
          itemId: "item-1",
          filePath: "/path/to/file.mp3",
          totalBytes: 1000000,
        },
      });

      // Wait for async operations to complete
      await new Promise((resolve) => setTimeout(resolve, 100));

      const state = get(downloads);
      expect(state.downloads[123].status).toBe("completed");
    });

    it("should handle failed event and refresh", async () => {
      const { downloads, initDownloadEvents } = await import("./downloads");

      // Setup mock to return downloading download when refresh is called
      mockInvoke.mockImplementation((command: string) => {
        if (command === "get_downloads") {
          return Promise.resolve({
            downloads: [
              {
                id: 123,
                itemId: "item-1",
                userId: "user-1",
                filePath: "/path/to/file.mp3",
                status: "downloading",
                progress: 0.5,
                bytesDownloaded: 500000,
                queuedAt: "2024-01-01T00:00:00Z",
                retryCount: 0,
                priority: 0,
                mediaType: "audio",
                downloadSource: "user",
              },
            ],
            stats: {
              total: 1,
              activeCount: 1,
              queuedCount: 0,
              completedCount: 0,
              failedCount: 0,
              pausedCount: 0,
            },
          });
        } else if (command === "mark_download_failed") {
          return Promise.resolve(undefined);
        }
        return Promise.reject(new Error(`Unexpected command: ${command}`));
      });

      await downloads.refresh("user-1");

      // Initialize event listener
      await initDownloadEvents();

      // Simulate failed event
      eventHandler!({
        payload: {
          type: "failed",
          downloadId: 123,
          itemId: "item-1",
          error: "Network timeout",
        },
      });

      // Wait for async operations to complete
      await new Promise((resolve) => setTimeout(resolve, 100));

      const state = get(downloads);
      expect(state.downloads[123].status).toBe("failed");
      expect(state.downloads[123].errorMessage).toBe("Network timeout");
    });

    it("should handle cancelled event and refresh", async () => {
      const { downloads, initDownloadEvents } = await import("./downloads");

      mockInvoke.mockResolvedValueOnce({
        downloads: [
          {
            id: 123,
            itemId: "item-1",
            userId: "user-1",
            filePath: "/path/to/file.mp3",
            status: "downloading",
            progress: 0.5,
            bytesDownloaded: 500000,
            queuedAt: "2024-01-01T00:00:00Z",
            retryCount: 0,
            priority: 0,
            mediaType: "audio",
            downloadSource: "user",
          },
        ],
        stats: {
          total: 1,
          activeCount: 1,
          queuedCount: 0,
          completedCount: 0,
          failedCount: 0,
          pausedCount: 0,
        },
      });

      await downloads.refresh("user-1");

      // Initialize event listener
      await initDownloadEvents();

      // Simulate cancelled event
      // Note: The cancelled event handler does NOT call refresh, it only removes from store
      eventHandler!({
        payload: {
          type: "cancelled",
          downloadId: 123,
          itemId: "item-1",
        },
      });

      // Wait for async operations to complete
      await new Promise((resolve) => setTimeout(resolve, 100));

      const state = get(downloads);
      expect(state.downloads[123]).toBeUndefined();
    });
  });

  describe("derived stores", () => {
    it("activeDownloads should filter downloading status", async () => {
      const { downloads, activeDownloads } = await import("./downloads");

      mockInvoke.mockImplementation((command: string) => {
        if (command === "get_downloads") {
          return Promise.resolve({
            downloads: [
              {
                id: 1,
                itemId: "item-1",
                userId: "user-1",
                filePath: "/path/1.mp3",
                status: "downloading",
                progress: 0.5,
                bytesDownloaded: 500,
                queuedAt: "2024-01-01T00:00:00Z",
                retryCount: 0,
                priority: 0,
                mediaType: "audio",
                downloadSource: "user",
              },
              {
                id: 2,
                itemId: "item-2",
                userId: "user-1",
                filePath: "/path/2.mp3",
                status: "completed",
                progress: 1.0,
                bytesDownloaded: 1000,
                queuedAt: "2024-01-01T00:00:00Z",
                retryCount: 0,
                priority: 0,
                mediaType: "audio",
                downloadSource: "user",
              },
              {
                id: 3,
                itemId: "item-3",
                userId: "user-1",
                filePath: "/path/3.mp3",
                status: "pending",
                progress: 0,
                bytesDownloaded: 0,
                queuedAt: "2024-01-01T00:00:00Z",
                retryCount: 0,
                priority: 0,
                mediaType: "audio",
                downloadSource: "user",
              },
            ],
            stats: {
              total: 3,
              activeCount: 1,
              queuedCount: 1,
              completedCount: 1,
              failedCount: 0,
              pausedCount: 0,
            },
          });
        }
        return Promise.reject(new Error(`Unexpected command: ${command}`));
      });

      await downloads.refresh("user-1");

      const active = get(activeDownloads);
      expect(active.length).toBe(1);
      expect(active[0].id).toBe(1);
      expect(active[0].status).toBe("downloading");
    });

    it("completedDownloads should filter completed status", async () => {
      const { downloads, completedDownloads } = await import("./downloads");

      mockInvoke.mockImplementation((command: string) => {
        if (command === "get_downloads") {
          return Promise.resolve({
            downloads: [
              {
                id: 1,
                itemId: "item-1",
                userId: "user-1",
                filePath: "/path/1.mp3",
                status: "downloading",
                progress: 0.5,
                bytesDownloaded: 500,
                queuedAt: "2024-01-01T00:00:00Z",
                retryCount: 0,
                priority: 0,
                mediaType: "audio",
                downloadSource: "user",
              },
              {
                id: 2,
                itemId: "item-2",
                userId: "user-1",
                filePath: "/path/2.mp3",
                status: "completed",
                progress: 1.0,
                bytesDownloaded: 1000,
                queuedAt: "2024-01-01T00:00:00Z",
                retryCount: 0,
                priority: 0,
                mediaType: "audio",
                downloadSource: "user",
              },
              {
                id: 3,
                itemId: "item-3",
                userId: "user-1",
                filePath: "/path/3.mp3",
                status: "completed",
                progress: 1.0,
                bytesDownloaded: 1000,
                queuedAt: "2024-01-01T00:00:00Z",
                retryCount: 0,
                priority: 0,
                mediaType: "audio",
                downloadSource: "user",
              },
            ],
            stats: {
              total: 3,
              activeCount: 1,
              queuedCount: 0,
              completedCount: 2,
              failedCount: 0,
              pausedCount: 0,
            },
          });
        }
        return Promise.reject(new Error(`Unexpected command: ${command}`));
      });

      await downloads.refresh("user-1");

      const completed = get(completedDownloads);
      expect(completed.length).toBe(2);
      expect(completed.every((d) => d.status === "completed")).toBe(true);
    });

    it("pendingDownloads should filter pending status", async () => {
      const { downloads, pendingDownloads } = await import("./downloads");

      mockInvoke.mockImplementation((command: string) => {
        if (command === "get_downloads") {
          return Promise.resolve({
            downloads: [
              {
                id: 1,
                itemId: "item-1",
                userId: "user-1",
                filePath: "/path/1.mp3",
                status: "pending",
                progress: 0,
                bytesDownloaded: 0,
                queuedAt: "2024-01-01T00:00:00Z",
                retryCount: 0,
                priority: 10,
                mediaType: "audio",
                downloadSource: "user",
              },
              {
                id: 2,
                itemId: "item-2",
                userId: "user-1",
                filePath: "/path/2.mp3",
                status: "completed",
                progress: 1.0,
                bytesDownloaded: 1000,
                queuedAt: "2024-01-01T00:00:00Z",
                retryCount: 0,
                priority: 0,
                mediaType: "audio",
                downloadSource: "user",
              },
              {
                id: 3,
                itemId: "item-3",
                userId: "user-1",
                filePath: "/path/3.mp3",
                status: "pending",
                progress: 0,
                bytesDownloaded: 0,
                queuedAt: "2024-01-01T00:00:00Z",
                retryCount: 0,
                priority: 5,
                mediaType: "audio",
                downloadSource: "user",
              },
            ],
            stats: {
              total: 3,
              activeCount: 0,
              queuedCount: 2,
              completedCount: 1,
              failedCount: 0,
              pausedCount: 0,
            },
          });
        }
        return Promise.reject(new Error(`Unexpected command: ${command}`));
      });

      await downloads.refresh("user-1");

      const pending = get(pendingDownloads);
      expect(pending.length).toBe(2);
      expect(pending.every((d) => d.status === "pending")).toBe(true);
    });

    it("failedDownloads should filter failed status", async () => {
      const { downloads, failedDownloads } = await import("./downloads");

      mockInvoke.mockImplementation((command: string) => {
        if (command === "get_downloads") {
          return Promise.resolve({
            downloads: [
              {
                id: 1,
                itemId: "item-1",
                userId: "user-1",
                filePath: "/path/1.mp3",
                status: "failed",
                progress: 0.5,
                bytesDownloaded: 500,
                queuedAt: "2024-01-01T00:00:00Z",
                retryCount: 3,
                priority: 0,
                mediaType: "audio",
                downloadSource: "user",
                errorMessage: "Network error",
              },
              {
                id: 2,
                itemId: "item-2",
                userId: "user-1",
                filePath: "/path/2.mp3",
                status: "completed",
                progress: 1.0,
                bytesDownloaded: 1000,
                queuedAt: "2024-01-01T00:00:00Z",
                retryCount: 0,
                priority: 0,
                mediaType: "audio",
                downloadSource: "user",
              },
              {
                id: 3,
                itemId: "item-3",
                userId: "user-1",
                filePath: "/path/3.mp3",
                status: "failed",
                progress: 0.3,
                bytesDownloaded: 300,
                queuedAt: "2024-01-01T00:00:00Z",
                retryCount: 2,
                priority: 0,
                mediaType: "audio",
                downloadSource: "user",
                errorMessage: "Timeout",
              },
            ],
            stats: {
              total: 3,
              activeCount: 0,
              queuedCount: 0,
              completedCount: 1,
              failedCount: 2,
              pausedCount: 0,
            },
          });
        }
        return Promise.reject(new Error(`Unexpected command: ${command}`));
      });

      await downloads.refresh("user-1");

      const failed = get(failedDownloads);
      expect(failed.length).toBe(2);
      expect(failed.every((d) => d.status === "failed")).toBe(true);
    });
  });

  describe("error handling", () => {
    it("should throw error when download_item fails", async () => {
      const { downloads } = await import("./downloads");

      mockInvoke.mockImplementation((command: string) => {
        if (command === "download_item") {
          return Promise.reject(new Error("Backend error: failed to queue download"));
        }
        return Promise.reject(new Error(`Unexpected command: ${command}`));
      });

      await expect(
        downloads.downloadItem("item-1", "user-1", "/path/to/file.mp3")
      ).rejects.toThrow("Backend error: failed to queue download");
    });

    it("should throw error when refresh fails", async () => {
      const { downloads } = await import("./downloads");

      mockInvoke.mockImplementation((command: string) => {
        if (command === "get_downloads") {
          return Promise.reject(new Error("Backend error: failed to fetch downloads"));
        }
        return Promise.reject(new Error(`Unexpected command: ${command}`));
      });

      await expect(
        downloads.refresh("user-1")
      ).rejects.toThrow("Backend error: failed to fetch downloads");
    });
  });
});
