import { describe, it, expect, vi, beforeEach } from "vitest";
import { get } from "svelte/store";

// UT-069: `isConnected` must follow backend server reachability ALONE, never
// navigator.onLine. See docs/specs/offline-downloaded-only-filter.md (DR-079).
//
// The connectivity store registers a `connectivity:changed` listener at import
// time and mirrors its payload into `isServerReachable`. We capture that
// listener via the mocked `listen`, then drive reachability directly while
// pinning navigator.onLine to the *opposite* value to prove it is ignored.

const h = vi.hoisted(() => {
  const listeners = new Map<string, (event: { payload: unknown }) => void>();
  return { listeners };
});

vi.mock("@tauri-apps/api/event", () => ({
  listen: vi.fn(async (name: string, cb: (event: { payload: unknown }) => void) => {
    h.listeners.set(name, cb);
    return () => h.listeners.delete(name);
  }),
}));

vi.mock("$lib/api/bindings", () => ({
  commands: {
    connectivityCheckServer: vi.fn(async () => true),
    connectivityGetStatus: vi.fn(async () => ({
      isServerReachable: true,
      lastChecked: null,
      connectionError: null,
      isChecking: false,
    })),
    connectivitySetServerUrl: vi.fn(async () => {}),
    connectivityStartMonitoring: vi.fn(async () => {}),
    connectivityStopMonitoring: vi.fn(async () => {}),
  },
}));

vi.mock("$app/environment", () => ({ browser: true }));

function setNavigatorOnLine(value: boolean) {
  Object.defineProperty(window.navigator, "onLine", {
    configurable: true,
    get: () => value,
  });
}

function emitReachable(isReachable: boolean) {
  const cb = h.listeners.get("connectivity:changed");
  if (!cb) throw new Error("connectivity:changed listener was not registered");
  cb({ payload: { isReachable } });
}

describe("isConnected follows server reachability alone (UT-069)", () => {
  beforeEach(() => {
    h.listeners.clear();
    vi.resetModules(); // fresh connectivity module ⇒ re-registers its listener
  });

  it("is false when the server is unreachable even though navigator.onLine is true", async () => {
    setNavigatorOnLine(true);
    const { isConnected } = await import("./connectivity");

    emitReachable(false);
    expect(get(isConnected)).toBe(false);
  });

  it("is true when the server is reachable even though navigator.onLine is false", async () => {
    setNavigatorOnLine(false);
    const { isConnected } = await import("./connectivity");

    emitReachable(true);
    expect(get(isConnected)).toBe(true);
  });
});
