/**
 * tests/fixtures/foundry-adapter.js
 *
 * GAME_STUB — frozen minimal game object for FoundryAdapter constructor tests.
 *
 * Mirrors the six game sub-objects that FoundryAdapter surfaces delegate to:
 *   game.settings, game.socket, game.users, game.user, game.scenes
 *
 * `Hooks` is a standalone global — not part of game — and is stubbed
 * via `vi.stubGlobal('Hooks', HOOKS_STUB)` in individual test files.
 * `ui.notifications` is similarly a standalone global.
 */

import { vi } from 'vitest';

/** Minimal game.settings stub. All methods are vi.fn(). */
const SETTINGS_STUB = {
  register: vi.fn(),
  get: vi.fn().mockReturnValue(null),
  set: vi.fn().mockResolvedValue(undefined),
};

/** Minimal game.socket stub. */
const SOCKET_STUB = {
  emit: vi.fn(),
  on: vi.fn(),
  off: vi.fn(),
};

/** A representative user object. */
const createUserWithFlags = (id, name, isGM, flags = {}) => {
  const flagStore = { ...flags };
  return Object.freeze({
    id,
    name,
    isGM,
    /**
     * Get a flag value for this user.
     * @param {string} scope - The flag scope/namespace
     * @param {string} key - The flag key
     * @returns {unknown|null} The flag value or null if not found
     */
    getFlag: (scope, key) => {
      const scopeKey = `${scope}.${key}`;
      return flagStore[scopeKey] ?? null;
    },
    /**
     * Set a flag value for this user.
     * @param {string} scope - The flag scope/namespace
     * @param {string} key - The flag key
     * @param {unknown} value - The value to set
     * @returns {Promise<unknown>} Resolves when set
     */
    setFlag: (scope, key, value) => {
      const scopeKey = `${scope}.${key}`;
      flagStore[scopeKey] = value;
      return Promise.resolve(value);
    },
  });
};

const GM_USER = createUserWithFlags('gm-user-1', 'GM', true);
const PLAYER_USER = createUserWithFlags('player-user-1', 'Player', false);

/** Minimal game.users map-like stub. */
const USERS_STUB = {
  get: vi.fn((id) => {
    if (id === GM_USER.id) return GM_USER;
    if (id === PLAYER_USER.id) return PLAYER_USER;
    return null;
  }),
  [Symbol.iterator]: vi.fn(function* () {
    yield GM_USER;
    yield PLAYER_USER;
  }),
};

/** Minimal game.user (current user) stub. */
const USER_STUB = Object.freeze({ id: GM_USER.id, name: GM_USER.name, isGM: true });

/** A representative scene object. */
const ACTIVE_SCENE = Object.freeze({ id: 'scene-1', name: 'Test Scene' });

/** Minimal game.scenes stub. */
const SCENES_STUB = {
  active: ACTIVE_SCENE,
  get: vi.fn((id) => (id === ACTIVE_SCENE.id ? ACTIVE_SCENE : null)),
};

/**
 * Frozen minimal game object for FoundryAdapter constructor tests.
 * Reset individual stubs between tests with `vi.clearAllMocks()` or per-spy.
 */
export const GAME_STUB = Object.freeze({
  settings: SETTINGS_STUB,
  socket: SOCKET_STUB,
  users: USERS_STUB,
  user: USER_STUB,
  scenes: SCENES_STUB,
});

/** Exported stubs for targeted assertions in tests. */
export { SETTINGS_STUB, SOCKET_STUB, USERS_STUB, USER_STUB, SCENES_STUB, GM_USER, PLAYER_USER, ACTIVE_SCENE };

/**
 * Minimal Hooks stub for vi.stubGlobal('Hooks', HOOKS_STUB).
 * Each method is a vi.fn().
 */
export const HOOKS_STUB = {
  on: vi.fn(),
  once: vi.fn(),
  off: vi.fn(),
  callAll: vi.fn(),
};

/**
 * Minimal ui.notifications stub for vi.stubGlobal('ui', UI_STUB).
 */
export const UI_STUB = Object.freeze({
  notifications: {
    info: vi.fn(),
    warn: vi.fn(),
    error: vi.fn(),
  },
});
