/**
 * Device ID service tests
 *
 * Tests the service layer that integrates with the Rust backend.
 * The Rust backend handles UUID generation and database storage.
 *
 * TRACES: UR-009 | DR-011
 */

import { describe, it, expect, vi, beforeEach } from "vitest";
import { getDeviceId, getDeviceIdSync, clearCache } from "./deviceId";

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

import { invoke } from "@tauri-apps/api/core";

describe("Device ID Service", () => {
  beforeEach(() => {
    clearCache();
    vi.clearAllMocks();
  });

  it("should retrieve device ID from backend", async () => {
    const mockDeviceId = "550e8400-e29b-41d4-a716-446655440000";
    (invoke as any).mockResolvedValue(mockDeviceId);

    const deviceId = await getDeviceId();

    expect(deviceId).toBe(mockDeviceId);
    expect(invoke).toHaveBeenCalledWith("device_get_id");
    expect(invoke).toHaveBeenCalledTimes(1);
  });

  it("should cache device ID in memory after first call", async () => {
    const mockDeviceId = "550e8400-e29b-41d4-a716-446655440000";
    (invoke as any).mockResolvedValue(mockDeviceId);

    const id1 = await getDeviceId();
    const id2 = await getDeviceId();

    expect(id1).toBe(id2);
    // Should only invoke backend once due to caching
    expect(invoke).toHaveBeenCalledTimes(1);
  });

  it("should return cached device ID synchronously after initialization", async () => {
    const mockDeviceId = "550e8400-e29b-41d4-a716-446655440000";
    (invoke as any).mockResolvedValue(mockDeviceId);

    await getDeviceId();
    const cachedId = getDeviceIdSync();

    expect(cachedId).toBe(mockDeviceId);
  });

  it("should return empty string from sync if not yet initialized", () => {
    const syncId = getDeviceIdSync();
    expect(syncId).toBe("");
  });

  it("should throw error when backend fails", async () => {
    (invoke as any).mockRejectedValue(new Error("Backend error"));

    await expect(getDeviceId()).rejects.toThrow("Failed to initialize device ID");
  });

  it("should clear cache on logout", async () => {
    const mockDeviceId = "550e8400-e29b-41d4-a716-446655440000";
    (invoke as any).mockResolvedValue(mockDeviceId);

    await getDeviceId();
    expect(getDeviceIdSync()).toBe(mockDeviceId);

    clearCache();
    expect(getDeviceIdSync()).toBe("");
  });

  it("should call backend again after cache is cleared", async () => {
    const mockDeviceId = "550e8400-e29b-41d4-a716-446655440000";
    (invoke as any).mockResolvedValue(mockDeviceId);

    await getDeviceId();
    clearCache();
    await getDeviceId();

    // Should call backend twice (once per getDeviceId call)
    expect(invoke).toHaveBeenCalledTimes(2);
  });
});
