import { test } from 'node:test';
import assert from 'node:assert/strict';
import { createStore } from 'jotai';
import type { CallPreferences } from './callPreferences';

// `makeCallPreferencesAtom(userId)` is a factory backed by `atomWithLocalStorage`.
// localStorage is read when the returned atom is created; we install an
// in-memory mock first so reads/writes resolve against it.
const CALL_PREFERENCES = 'callPreferences';
const storeKeyFor = (userId: string): string => `${CALL_PREFERENCES}${userId}`;

const installStorage = (): Map<string, string> => {
  const map = new Map<string, string>();
  (globalThis as { localStorage?: unknown }).localStorage = {
    getItem: (k: string) => (map.has(k) ? map.get(k)! : null),
    setItem: (k: string, v: string) => {
      map.set(k, v);
    },
    removeItem: (k: string) => {
      map.delete(k);
    },
  };
  return map;
};

installStorage();
// eslint-disable-next-line import/first
import { makeCallPreferencesAtom } from './callPreferences';

const USER = '@user:server';

test('defaults to mic on, sound on, video off', () => {
  installStorage();
  const prefsAtom = makeCallPreferencesAtom(USER);
  const store = createStore();
  assert.deepEqual(store.get(prefsAtom), {
    microphone: true,
    video: false,
    sound: true,
  });
});

test('forces video to false on LOAD even when stored as true', () => {
  const backing = installStorage();
  backing.set(storeKeyFor(USER), JSON.stringify({ microphone: false, video: true, sound: false }));

  const prefsAtom = makeCallPreferencesAtom(USER);
  const store = createStore();
  const prefs = store.get(prefsAtom);

  // video is overridden, but mic/sound are preserved from storage.
  assert.equal(prefs.video, false);
  assert.equal(prefs.microphone, false);
  assert.equal(prefs.sound, false);
});

test('forces video to false on PERSIST even when set to true', () => {
  const backing = installStorage();
  const prefsAtom = makeCallPreferencesAtom(USER);
  const store = createStore();

  store.set(prefsAtom, { microphone: true, video: true, sound: true });

  const raw = backing.get(storeKeyFor(USER));
  assert.ok(raw);
  const persisted = JSON.parse(raw!) as CallPreferences;
  assert.equal(persisted.video, false);
  // mic/sound persisted as given.
  assert.equal(persisted.microphone, true);
  assert.equal(persisted.sound, true);
});

test('the in-memory atom value also has video forced off after a write', () => {
  installStorage();
  const prefsAtom = makeCallPreferencesAtom(USER);
  const store = createStore();

  // atomWithLocalStorage write-through stores newValue verbatim on the atom,
  // while only the persisted copy is sanitized. The next load re-sanitizes.
  store.set(prefsAtom, { microphone: true, video: true, sound: true });

  // Re-create the atom to model a fresh load from the (sanitized) storage.
  const reloaded = makeCallPreferencesAtom(USER);
  assert.equal(store.get(reloaded).video, false);
});

test('preserves mic/sound toggles across a persist + reload cycle', () => {
  installStorage();
  const prefsAtom = makeCallPreferencesAtom(USER);
  const store = createStore();

  store.set(prefsAtom, { microphone: false, video: false, sound: false });

  const reloaded = makeCallPreferencesAtom(USER);
  const prefs = store.get(reloaded);
  assert.equal(prefs.microphone, false);
  assert.equal(prefs.sound, false);
  assert.equal(prefs.video, false);
});

test('preferences are scoped per userId', () => {
  const backing = installStorage();
  const userA = '@a:s';
  const userB = '@b:s';
  const atomA = makeCallPreferencesAtom(userA);
  const atomB = makeCallPreferencesAtom(userB);
  const store = createStore();

  store.set(atomA, { microphone: false, video: false, sound: true });
  store.set(atomB, { microphone: true, video: false, sound: false });

  assert.ok(backing.has(storeKeyFor(userA)));
  assert.ok(backing.has(storeKeyFor(userB)));
  assert.equal(store.get(atomA).microphone, false);
  assert.equal(store.get(atomB).microphone, true);
});
