/**
 * Regression for the review's H3: self-deleting an upload and banning a user with
 * hide_uploads mutated visibility server-side but broadcast nothing, so the
 * content lingered on every other viewer's feed (and the projector diashow) until
 * a manual reload. Both now emit SSE so clients evict live.
 */
import { test, expect } from '../../fixtures/test';
import { seedUpload } from '../../helpers/seed';
import { SseListener } from '../../helpers/sse-listener';
import { BASE } from '../../helpers/env';

test.describe('Host — live SSE eviction (H3)', () => {
  test('self-deleting an upload broadcasts upload-deleted', async ({ guest }) => {
    const g = await guest('SelfDeleter');
    const uploadId = await seedUpload(g.jwt, { caption: 'delete me' });

    const sse = new SseListener();
    await sse.start(g.jwt);

    const res = await fetch(`${BASE}/api/v1/upload/${uploadId}`, {
      method: 'DELETE',
      headers: { Authorization: `Bearer ${g.jwt}` },
    });
    expect(res.status).toBe(204);

    await sse.waitForEvent('upload-deleted', (e) => e.data.upload_id === uploadId);
  });

  test('banning a user broadcasts user-hidden', async ({ api, host, guest }) => {
    const target = await guest('HideTarget');
    await seedUpload(target.jwt, { caption: 'should vanish' });

    const sse = new SseListener();
    await sse.start(host.jwt);

    await api.banUser(host.jwt, target.userId);

    await sse.waitForEvent('user-hidden', (e) => e.data.user_id === target.userId);
  });

  // Frontend regression: the broadcasts above are inert if the client never
  // registers the event name (the KNOWN_EVENTS gap that shipped both eviction
  // handlers as dead code). Drive a real browser feed and assert LIVE eviction —
  // this fails if 'user-hidden' is missing from KNOWN_EVENTS, unlike the
  // backend-only SseListener checks above.
  test('a hidden user is evicted from an open feed without reload (frontend)', async ({
    page,
    api,
    host,
    guest,
    signIn,
  }) => {
    const viewer = await guest('LiveEvictViewer');
    const target = await guest('LiveEvictTarget');
    await seedUpload(target.jwt, { caption: 'evict-me-live-xyz' });

    await signIn(page, viewer); // lands on the event-wide /feed
    await expect(page.getByText('evict-me-live-xyz').first()).toBeVisible();

    // Host hides the target — the viewer's feed must drop the card via SSE, no reload.
    await api.banUser(host.jwt, target.userId);
    await expect(page.getByText('evict-me-live-xyz')).toHaveCount(0, { timeout: 15_000 });
  });
});
