import { describe, expect, it, vi } from 'vitest';
import { OIDC_BROWSER_SESSION_CREDENTIAL } from '../api';
import {
  reconcileOIDCBrowserSessionAfterRuntimeChange,
  restoreOIDCBrowserSession,
} from './oidc-browser-session';

describe('OIDC browser session lifecycle', () => {
  it('restores a shared cookie session in a fresh tab', async () => {
    vi.stubGlobal('fetch', vi.fn().mockResolvedValue(new Response(JSON.stringify({
      sub: 'platform-user', source: 'oidc', gatewayUserId: 'gateway-user',
    }), { status: 200, headers: { 'Content-Type': 'application/json' } })));

    const restored = await restoreOIDCBrowserSession();

    expect(restored?.credential).toBe(OIDC_BROWSER_SESSION_CREDENTIAL);
    expect(restored?.user.sub).toBe('platform-user');
  });

  it('treats a missing or expired shared cookie as a signed-out tab', async () => {
    vi.stubGlobal('fetch', vi.fn().mockResolvedValue(new Response(JSON.stringify({
      error: { message: 'unauthorized', status: 401 },
    }), { status: 401, headers: { 'Content-Type': 'application/json' } })));

    await expect(restoreOIDCBrowserSession()).resolves.toBeNull();
  });

  it('resets App authentication when an OIDC sentinel session re-probe returns 401', async () => {
    const resetAuthenticatedSession = vi.fn();
    const onRestored = vi.fn();
    const fetchMock = vi.fn().mockResolvedValue(new Response(JSON.stringify({
      error: { message: 'unauthorized', status: 401 },
    }), { status: 401, headers: { 'Content-Type': 'application/json' } }));
    vi.stubGlobal('fetch', fetchMock);

    await expect(reconcileOIDCBrowserSessionAfterRuntimeChange({
      credential: OIDC_BROWSER_SESSION_CREDENTIAL,
      oidcEnabled: true,
      onReset: resetAuthenticatedSession,
      onRestored,
    })).resolves.toBe('reset');

    expect(fetchMock).toHaveBeenCalledOnce();
    expect(resetAuthenticatedSession).toHaveBeenCalledOnce();
    expect(onRestored).not.toHaveBeenCalled();
  });

  it('resets App authentication without probing /me when identity is disabled', async () => {
    const resetAuthenticatedSession = vi.fn();
    const onRestored = vi.fn();
    const fetchMock = vi.fn();
    vi.stubGlobal('fetch', fetchMock);

    await expect(reconcileOIDCBrowserSessionAfterRuntimeChange({
      credential: OIDC_BROWSER_SESSION_CREDENTIAL,
      oidcEnabled: false,
      onReset: resetAuthenticatedSession,
      onRestored,
    })).resolves.toBe('reset');

    expect(fetchMock).not.toHaveBeenCalled();
    expect(resetAuthenticatedSession).toHaveBeenCalledOnce();
    expect(onRestored).not.toHaveBeenCalled();
  });
});
