/**
 * "Sign out everywhere" — DELETE /api/v1/sessions. A security control (revoke every device after a
 * lost/stolen phone) that had ZERO coverage. Sessions are validated per-request against the DB
 * (auth middleware resolves the token hash to a live session row), so revocation is observable: a
 * revoked token must stop authenticating.
 */
import { test, expect } from '../../fixtures/test';
import { BASE } from '../../helpers/env';

const ctx = (jwt: string) =>
  fetch(`${BASE}/api/v1/me/context`, { headers: { Authorization: `Bearer ${jwt}` } });

test.describe('Auth — sign out everywhere', () => {
  test("DELETE /sessions revokes ALL of the caller's sessions, not just the current one", async ({
    api,
    guest,
    db,
  }) => {
    // Two devices for one guest: the join session, plus a second session from a recover login.
    const g = await guest('MultiDevice');
    const second = await api.recover(g.displayName, g.pin);
    const secondJwt = second.body.jwt;

    // Both tokens work, and there really are two distinct sessions.
    expect((await ctx(g.jwt)).status).toBe(200);
    expect((await ctx(secondJwt)).status).toBe(200);
    expect(await db.countSessionsForUser(g.userId)).toBeGreaterThanOrEqual(2);

    // Sign out everywhere, authenticated as device one.
    const res = await fetch(`${BASE}/api/v1/sessions`, {
      method: 'DELETE',
      headers: { Authorization: `Bearer ${g.jwt}` },
    });
    expect(res.status).toBe(204);

    // BOTH devices are now logged out — the whole point of the control. If it only killed the
    // caller's own session, device two would still be live and a stolen phone would keep access.
    expect((await ctx(g.jwt)).status, 'the calling device is signed out').toBe(401);
    expect((await ctx(secondJwt)).status, 'the OTHER device is signed out too').toBe(401);
    expect(await db.countSessionsForUser(g.userId)).toBe(0);
  });

  test("one user signing out everywhere does not touch another user's sessions", async ({
    guest,
  }) => {
    const a = await guest('SignsOut');
    const b = await guest('StaysIn');

    await fetch(`${BASE}/api/v1/sessions`, {
      method: 'DELETE',
      headers: { Authorization: `Bearer ${a.jwt}` },
    });

    expect((await ctx(a.jwt)).status).toBe(401);
    expect((await ctx(b.jwt)).status, "another user's session must be untouched").toBe(200);
  });
});
