/**
 * User Impersonation module — unit tests.
 */

import { describe, it, expect } from 'vitest';
import { StartImpersonationSchema, StopImpersonationSchema } from './types.js';

describe('StartImpersonationSchema', () => {
  it('accepts valid input', () => {
    const result = StartImpersonationSchema.parse({
      targetUserId: 'user-123',
      reason: 'Debugging timer sync issue',
    });
    expect(result.targetUserId).toBe('user-123');
    expect(result.reason).toBe('Debugging timer sync issue');
  });

  it('rejects empty targetUserId', () => {
    expect(() => StartImpersonationSchema.parse({ targetUserId: '', reason: 'test' })).toThrow();
  });

  it('rejects empty reason', () => {
    expect(() => StartImpersonationSchema.parse({ targetUserId: 'u1', reason: '' })).toThrow();
  });

  it('rejects reason over 500 chars', () => {
    expect(() =>
      StartImpersonationSchema.parse({ targetUserId: 'u1', reason: 'x'.repeat(501) })
    ).toThrow();
  });
});

describe('StopImpersonationSchema', () => {
  it('accepts valid sessionId', () => {
    const result = StopImpersonationSchema.parse({ sessionId: 'imp-abc123' });
    expect(result.sessionId).toBe('imp-abc123');
  });

  it('rejects empty sessionId', () => {
    expect(() => StopImpersonationSchema.parse({ sessionId: '' })).toThrow();
  });
});

// ── Route-level behaviour tests (schema + business rule validation) ──

describe('Impersonation business rules', () => {
  it('requireAdmin rejects non-admin role', () => {
    // Simulates the requireAdmin guard in routes.ts
    const fakeReq = { jwtPayload: { sub: 'user-1', role: 'viewer' } };
    const isAdmin = fakeReq.jwtPayload.role === 'admin';
    expect(isAdmin).toBe(false);
  });

  it('requireAdmin rejects missing jwt', () => {
    const fakeReq = { jwtPayload: undefined } as { jwtPayload?: { sub: string; role?: string } };
    expect(fakeReq.jwtPayload?.sub).toBeUndefined();
  });

  it('self-impersonation is detected', () => {
    const adminUserId = 'admin-1';
    const input = StartImpersonationSchema.parse({ targetUserId: 'admin-1', reason: 'test' });
    expect(input.targetUserId === adminUserId).toBe(true);
  });

  it('ImpersonationSessionDoc has correct shape', () => {
    const doc = {
      id: 'imp_abc',
      productId: 'test',
      adminUserId: 'admin-1',
      targetUserId: 'user-2',
      reason: 'Debug issue',
      active: true,
      startedAt: new Date().toISOString(),
      endedAt: null,
      createdAt: new Date().toISOString(),
    };
    expect(doc.active).toBe(true);
    expect(doc.endedAt).toBeNull();
    expect(doc.id).toMatch(/^imp_/);
    expect(doc.productId).toBe('test');
  });
});
