import 'reflect-metadata';
import { readFileSync } from 'node:fs';
import { resolve } from 'node:path';
import { validateSync } from 'class-validator';
import { describe, expect, it, vi } from 'vitest';
import { SendMessageDto } from '../../conversations/conversations.dto.js';
import { ChatRequestDto } from '../chat.dto.js';
import { validateSocketSession } from '../chat.gateway-auth.js';

describe('Chat controller source hardening', () => {
  it('applies AuthGuard and reads the current user', () => {
    const source = readFileSync(resolve('src/chat/chat.controller.ts'), 'utf8');

    expect(source).toContain('@UseGuards(AuthGuard)');
    expect(source).toContain('@CurrentUser() user: AuthenticatedUserLike');
    expect(source).toContain('const scope = scopeFromUser(user);');
  });
});

describe('WebSocket session authentication', () => {
  it('returns null when the handshake does not resolve to a session', async () => {
    const result = await validateSocketSession(
      {},
      {
        api: {
          getSession: vi.fn().mockResolvedValue(null),
        },
      },
    );

    expect(result).toBeNull();
  });

  it('returns the resolved session when Better Auth accepts the headers', async () => {
    const session = { user: { id: 'user-1' }, session: { id: 'session-1' } };

    const result = await validateSocketSession(
      { cookie: 'session=abc' },
      {
        api: {
          getSession: vi.fn().mockResolvedValue(session),
        },
      },
    );

    expect(result).toEqual(session);
  });
});

describe('Chat DTO validation', () => {
  it('rejects unsupported message roles', () => {
    const dto = Object.assign(new SendMessageDto(), {
      content: 'hello',
      role: 'moderator',
    });

    const errors = validateSync(dto);

    expect(errors.length).toBeGreaterThan(0);
  });

  it('rejects oversized conversation message content above 10000 characters', () => {
    const dto = Object.assign(new SendMessageDto(), {
      content: 'x'.repeat(10_001),
      role: 'user',
    });

    const errors = validateSync(dto);

    expect(errors.length).toBeGreaterThan(0);
  });

  it('rejects oversized chat content above 10000 characters', () => {
    const dto = Object.assign(new ChatRequestDto(), {
      content: 'x'.repeat(10_001),
    });

    const errors = validateSync(dto);

    expect(errors.length).toBeGreaterThan(0);
  });
});
