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

tap.test('checks live TCP reachability and sends hkavr-compatible XML commands', async () => {
  const requests: string[] = [];
  const server = createServer((socketArg) => {
    socketArg.setEncoding('utf8');
    socketArg.on('data', (chunkArg) => {
      requests.push(String(chunkArg));
      socketArg.write('HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n', 'utf8');
    });
  });

  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 HarmanKardonAvrClient({
      host: '127.0.0.1',
      port,
      timeoutMs: 500,
      responseIdleMs: 30,
      state: { muted: false },
    });

    const snapshot = await client.getSnapshot();
    await client.execute({ command: 'turn_on' });
    await client.execute({ command: 'select_source', source: 'TV' });
    await client.execute({ command: 'mute', muted: true });

    expect(snapshot.online).toBeTrue();
    expect(requests.some((requestArg) => requestArg.includes('<name>heart-alive</name>'))).toBeTrue();
    expect(requests.some((requestArg) => requestArg.includes('<name>power-on</name>'))).toBeTrue();
    expect(requests.some((requestArg) => requestArg.includes('<name>source-selection</name>') && requestArg.includes('<para>TV</para>'))).toBeTrue();
    expect(requests.some((requestArg) => requestArg.includes('<name>mute-toggle</name>'))).toBeTrue();
  } finally {
    await new Promise<void>((resolve, reject) => server.close((errorArg) => errorArg ? reject(errorArg) : resolve()));
  }
});

tap.test('refuses targeted mute when current mute state is not represented', async () => {
  const client = new HarmanKardonAvrClient({
    commandExecutor: {
      execute: async () => ['HTTP/1.1 200 OK'],
    },
  });

  let error: unknown;
  try {
    await client.execute({ command: 'mute', muted: true });
  } catch (errorArg) {
    error = errorArg;
  }

  expect(error instanceof Error ? error.message : String(error)).toContain('requires known current mute state');
});

export default tap.start();
