import {
  afterEach,
  beforeEach,
  describe,
  expect,
  it
} from 'vitest';
import { ClientInstanceService } from './client-instance.service';

const SESSION_STORAGE_KEY = 'metoyou.clientInstanceId';
const LEGACY_LOCAL_STORAGE_KEY = 'metoyou.clientInstanceId';

describe('ClientInstanceService', () => {
  const sessionStorage = new Map<string, string>();
  const localStorage = new Map<string, string>();

  beforeEach(() => {
    sessionStorage.clear();
    localStorage.clear();

    vi.stubGlobal('sessionStorage', {
      getItem: (key: string) => sessionStorage.get(key) ?? null,
      setItem: (key: string, value: string) => { sessionStorage.set(key, value); },
      removeItem: (key: string) => { sessionStorage.delete(key); }
    });

    vi.stubGlobal('localStorage', {
      getItem: (key: string) => localStorage.get(key) ?? null,
      setItem: (key: string, value: string) => { localStorage.set(key, value); },
      removeItem: (key: string) => { localStorage.delete(key); }
    });
  });

  afterEach(() => {
    vi.unstubAllGlobals();
  });

  it('creates and persists a stable id for the same tab session', () => {
    const service = new ClientInstanceService();
    const first = service.getClientInstanceId();
    const second = new ClientInstanceService().getClientInstanceId();

    expect(first).toMatch(/^[0-9a-f-]{36}$/i);
    expect(second).toBe(first);
    expect(sessionStorage.get(SESSION_STORAGE_KEY)).toBe(first);
  });

  it('uses independent ids across separate tab sessions', () => {
    sessionStorage.set(SESSION_STORAGE_KEY, 'tab-a');

    const tabA = new ClientInstanceService().getClientInstanceId();

    sessionStorage.clear();
    sessionStorage.set(SESSION_STORAGE_KEY, 'tab-b');

    const tabB = new ClientInstanceService().getClientInstanceId();

    expect(tabA).toBe('tab-a');
    expect(tabB).toBe('tab-b');
  });

  it('does not reuse legacy localStorage ids that collide across tabs or synced browsers', () => {
    localStorage.set(LEGACY_LOCAL_STORAGE_KEY, 'synced-device-id');

    const id = new ClientInstanceService().getClientInstanceId();

    expect(id).not.toBe('synced-device-id');
    expect(sessionStorage.get(SESSION_STORAGE_KEY)).toBe(id);
    expect(localStorage.has(LEGACY_LOCAL_STORAGE_KEY)).toBe(false);
  });
});
