import { expect, tap } from '@git.zone/tstest/tapbundle';
import { BluesoundIntegration, type IBluesoundRawCommandRequest, type IBluesoundSnapshot } from '../../ts/integrations/bluesound/index.js';

const snapshot: IBluesoundSnapshot = {
  online: true,
  source: 'snapshot',
  players: [{
    host: '192.168.1.10',
    port: 11000,
    syncStatus: {
      id: '192.168.1.10:11000',
      mac: 'AA:BB:CC:DD:EE:01',
      name: 'Living Room',
      brand: 'Bluesound',
      model: 'NODE2I',
      modelName: 'NODE 2i',
      followers: [{ ip: '192.168.1.11', port: 11000 }],
      volume: 35,
    },
    status: { state: 'pause', volume: 20, mute: false, streamUrl: 'http://radio.example/jazz.mp3' },
    presets: [{ id: 1, name: 'Jazz Radio', url: 'http://radio.example/jazz.mp3' }],
    inputs: [{ id: 'linein', text: 'Analog Input', url: 'Capture:linein' }],
    available: true,
  }, {
    host: '192.168.1.11',
    port: 11000,
    syncStatus: {
      id: '192.168.1.11:11000',
      mac: 'AA:BB:CC:DD:EE:02',
      name: 'Kitchen',
      brand: 'Bluesound',
      model: 'PULSE',
      modelName: 'PULSE Flex',
      leader: { ip: '192.168.1.10', port: 11000 },
      volume: 35,
    },
    status: { state: 'pause', volume: 25, mute: false },
    presets: [],
    inputs: [],
    available: true,
  }],
};

tap.test('models Bluesound playback volume source preset and group commands through an executor', async () => {
  const commands: IBluesoundRawCommandRequest[] = [];
  const runtime = await new BluesoundIntegration().setup({
    snapshot,
    commandExecutor: {
      execute: async (requestArg) => {
        commands.push(requestArg);
        return { status: 200, body: '<ok />' };
      },
    },
  }, {});

  const play = await runtime.callService!({ domain: 'media_player', service: 'media_play', target: { entityId: 'media_player.living_room' } });
  const volume = await runtime.callService!({ domain: 'media_player', service: 'volume_set', target: { entityId: 'media_player.living_room' }, data: { volume_level: 0.35 } });
  const source = await runtime.callService!({ domain: 'media_player', service: 'select_source', target: { entityId: 'media_player.living_room' }, data: { source: 'Analog Input' } });
  const preset = await runtime.callService!({ domain: 'bluesound', service: 'play_preset', target: { entityId: 'media_player.living_room' }, data: { preset: 'Jazz Radio' } });
  const join = await runtime.callService!({ domain: 'media_player', service: 'join', target: { entityId: 'media_player.living_room' }, data: { group_members: ['media_player.kitchen'] } });
  const unjoin = await runtime.callService!({ domain: 'media_player', service: 'unjoin', target: { entityId: 'media_player.kitchen' } });

  expect(play.success).toBeTrue();
  expect(volume.success).toBeTrue();
  expect(source.success).toBeTrue();
  expect(preset.success).toBeTrue();
  expect(join.success).toBeTrue();
  expect(unjoin.success).toBeTrue();
  expect(commands.map((commandArg) => commandArg.path)).toEqual(['/Play', '/Volume', '/Play', '/Preset', '/AddSlave', '/RemoveSlave']);
  expect(commands[1].parameters).toEqual({ level: 35 });
  expect(commands[2].parameters).toEqual({ url: 'Capture:linein' });
  expect(commands[3].parameters).toEqual({ id: 1 });
  expect(commands[4].parameters).toEqual({ slave: '192.168.1.11', port: 11000 });
  expect(commands[5].host).toEqual('192.168.1.10');
  expect(commands[5].parameters).toEqual({ slave: '192.168.1.11', port: 11000 });
});

tap.test('does not report live command success for static snapshots without transport', async () => {
  const runtime = await new BluesoundIntegration().setup({ snapshot }, {});
  const result = await runtime.callService!({ domain: 'media_player', service: 'media_play', target: { entityId: 'media_player.living_room' } });

  expect(result.success).toBeFalse();
  expect(result.error?.includes('config.host or commandExecutor')).toBeTrue();
});

tap.test('does not execute playback commands on grouped followers', async () => {
  const commands: IBluesoundRawCommandRequest[] = [];
  const runtime = await new BluesoundIntegration().setup({
    snapshot,
    commandExecutor: {
      execute: async (requestArg) => {
        commands.push(requestArg);
        return { status: 200, body: '<ok />' };
      },
    },
  }, {});

  const result = await runtime.callService!({ domain: 'media_player', service: 'media_play', target: { entityId: 'media_player.kitchen' } });

  expect(result.success).toBeTrue();
  expect(commands.length).toEqual(0);
  expect((result.data as { skipped?: boolean }).skipped).toBeTrue();
});

export default tap.start();
