import { describe, it, expect } from 'vitest';
import { CommandRegistry } from './registry.js';

describe('CommandRegistry', () => {
  it('registers commands and retrieves by name/alias', () => {
    const registry = new CommandRegistry();
    registry.register({
      name: 'help',
      aliases: ['h'],
      description: 'show help',
      execute: async () => ({ handled: true, text: 'ok' }),
    });

    expect(registry.get('help')?.name).toBe('help');
    expect(registry.get('/help')?.name).toBe('help');
    expect(registry.get('h')?.name).toBe('help');
    expect(registry.get('/h')?.name).toBe('help');
    expect(registry.list()).toHaveLength(1);
  });

  it('parses slash command input', () => {
    const registry = new CommandRegistry();

    expect(registry.isCommand('/help')).toBe(true);
    expect(registry.parse('/model fast')).toEqual({
      name: 'model',
      args: ['fast'],
    });
    expect(registry.parse('hello')).toBeNull();
    expect(registry.parse('/')).toBeNull();
  });

  it('executes known command and returns handled result', async () => {
    const registry = new CommandRegistry();
    registry.register({
      name: 'status',
      description: 'show status',
      execute: async (_args, ctx) => ({ handled: true, text: `ok:${ctx.channel}` }),
    });

    const result = await registry.execute('/status', {
      channel: 'telegram',
      senderId: 'u1',
      sessionId: 'telegram:u1',
      rawInput: '/status',
    });

    expect(result).toEqual({ handled: true, text: 'ok:telegram' });
  });

  it('returns handled=false for unknown commands', async () => {
    const registry = new CommandRegistry();

    const result = await registry.execute('/unknown', {
      channel: 'telegram',
      senderId: 'u1',
      sessionId: 'telegram:u1',
      rawInput: '/unknown',
    });

    expect(result).toEqual({ handled: false, text: '' });
  });

  it('catches handler errors and returns safe message', async () => {
    const registry = new CommandRegistry();
    registry.register({
      name: 'boom',
      description: 'throws',
      execute: async () => {
        throw new Error('bad things');
      },
    });

    const result = await registry.execute('/boom', {
      channel: 'telegram',
      senderId: 'u1',
      sessionId: 'telegram:u1',
      rawInput: '/boom',
    });

    expect(result.handled).toBe(true);
    expect(result.text).toContain('Command failed: bad things');
  });
});
