import { expect, tap } from '@git.zone/tstest/tapbundle';
import { HarmonyIntegration, type IHarmonyCommand, type IHarmonyConfig } from '../../ts/integrations/harmony/index.js';

const baseConfig = (commandsArg: IHarmonyCommand[] = []): IHarmonyConfig => ({
  host: '192.168.1.40',
  name: 'Living Room Harmony',
  remoteId: '123456789',
  defaultActivity: 'Watch TV',
  snapshot: {
    deviceInfo: {
      id: '123456789',
      name: 'Living Room Harmony',
      host: '192.168.1.40',
      remoteId: '123456789',
    },
    state: {
      available: true,
      currentActivity: 'PowerOff',
      currentActivityId: '-1',
      lastActivity: 'Listen to Music',
    },
    activities: [
      { id: '-1', label: 'PowerOff', isPowerOff: true },
      { id: '111', label: 'Watch TV' },
      { id: '222', label: 'Listen to Music' },
    ],
    devices: [
      {
        id: '333',
        label: 'Television',
        commands: [{ name: 'VolumeUp' }, { name: 'Mute' }],
      },
    ],
  },
  executor: async (commandArg) => {
    commandsArg.push(commandArg);
  },
});

tap.test('models Harmony activity and remote commands through an injected executor', async () => {
  const commands: IHarmonyCommand[] = [];
  const runtime = await new HarmonyIntegration().setup(baseConfig(commands), {});

  expect((await runtime.callService?.({ domain: 'remote', service: 'turn_on', target: {}, data: { activity: 'Watch TV' } }))?.success).toBeTrue();
  expect(commands[0].action).toEqual('start_activity');
  expect(commands[0].activityId).toEqual('111');
  expect(commands[0].activity).toEqual('Watch TV');

  expect((await runtime.callService?.({ domain: 'remote', service: 'send_command', target: {}, data: { device: 'Television', command: ['VolumeUp', 'Mute'], num_repeats: 2, hold_secs: 0.25 } }))?.success).toBeTrue();
  expect(commands[1].action).toEqual('send_command');
  expect(commands[1].deviceId).toEqual('333');
  expect(commands[1].numRepeats).toEqual(2);
  expect(commands[1].holdSecs).toEqual(0.25);
  expect(commands[1].sequence?.map((stepArg) => stepArg.command)).toEqual(['VolumeUp', 'Mute', 'VolumeUp', 'Mute']);

  expect((await runtime.callService?.({ domain: 'harmony', service: 'change_channel', target: {}, data: { channel: 101 } }))?.success).toBeTrue();
  expect(commands[2].action).toEqual('change_channel');
  expect(commands[2].channel).toEqual(101);

  expect((await runtime.callService?.({ domain: 'select', service: 'select_option', target: {}, data: { option: 'power_off' } }))?.success).toBeTrue();
  expect(commands[3].action).toEqual('power_off');
  expect(commands[3].activity).toEqual('PowerOff');
});

tap.test('returns explicit unsupported errors without an executor', async () => {
  const runtime = await new HarmonyIntegration().setup({ host: '192.168.1.40', activities: [{ id: '111', label: 'Watch TV' }] }, {});
  const result = await runtime.callService?.({ domain: 'remote', service: 'turn_on', target: {}, data: { activity: 'Watch TV' } });

  expect(result?.success).toBeFalse();
  expect(result?.error).toContain('requires an injected client/executor');
});

tap.test('honors explicit Previous Active Activity over the configured default', async () => {
  const commands: IHarmonyCommand[] = [];
  const runtime = await new HarmonyIntegration().setup(baseConfig(commands), {});
  const result = await runtime.callService?.({ domain: 'remote', service: 'turn_on', target: {}, data: { activity: 'Previous Active Activity' } });

  expect(result?.success).toBeTrue();
  expect(commands[0].activity).toEqual('Listen to Music');
  expect(commands[0].activityId).toEqual('222');
});

tap.test('does not implement cloud-backed sync', async () => {
  const runtime = await new HarmonyIntegration().setup(baseConfig([]), {});
  const result = await runtime.callService?.({ domain: 'harmony', service: 'sync', target: {} });

  expect(result?.success).toBeFalse();
  expect(result?.error).toContain('cloud-backed');
});

export default tap.start();
