import { createServer } from 'node:net';
import { expect, tap } from '@git.zone/tstest/tapbundle';
import { MediaroomClient, MediaroomIntegration, MediaroomMapper } from '../../ts/integrations/mediaroom/index.js';

tap.test('probes and controls Mediaroom over the native TCP key protocol', async () => {
  const received: string[] = [];
  const server = createServer((socketArg) => {
    socketArg.write('HELLO!');
    let buffer = '';
    socketArg.on('data', (chunkArg) => {
      buffer += chunkArg.toString('utf8');
      const lines = buffer.split('\n');
      buffer = lines.pop() || '';
      for (const line of lines) {
        if (line.trim()) {
          received.push(line.trim());
          socketArg.write('OK\n');
        }
      }
    });
  });

  await new Promise<void>((resolve) => server.listen(0, '127.0.0.1', resolve));
  try {
    const address = server.address();
    const port = typeof address === 'object' && address ? address.port : 0;
    const client = new MediaroomClient({ host: '127.0.0.1', port, timeoutMs: 1000, keyDelayMs: 0 });
    const snapshot = await client.getSnapshot(true);
    const entities = MediaroomMapper.toEntities(snapshot);
    const runtime = await new MediaroomIntegration().setup({ host: '127.0.0.1', port, timeoutMs: 1000, keyDelayMs: 0 }, {});
    const volume = await runtime.callService!({ domain: 'media_player', service: 'volume_up', target: {} });
    const channel = await runtime.callService!({ domain: 'media_player', service: 'play_media', target: {}, data: { media_type: 'channel', media_id: '12' } });

    expect(snapshot.online).toBeTrue();
    expect(snapshot.source).toEqual('tcp');
    expect(entities[0].platform).toEqual('media_player');
    expect(entities[0].state).toEqual('unknown');
    expect(volume.success).toBeTrue();
    expect(channel.success).toBeTrue();
    expect(received.includes('key=175')).toBeTrue();
    expect(received.includes('key=49')).toBeTrue();
    expect(received.includes('key=50')).toBeTrue();
    expect(received.includes('key=13')).toBeTrue();
    await runtime.destroy();
  } finally {
    await new Promise<void>((resolve, reject) => server.close((errorArg) => errorArg ? reject(errorArg) : resolve()));
  }
});

export default tap.start();
