import { expect, tap } from '@git.zone/tstest/tapbundle';
import { ElgatoConfigFlow, ElgatoMapper, createElgatoDiscoveryDescriptor, type IElgatoRawData } from '../../ts/integrations/elgato/index.js';

tap.test('matches Elgato zeroconf records and creates config flow output', async () => {
  const descriptor = createElgatoDiscoveryDescriptor();
  const matcher = descriptor.getMatchers().find((matcherArg) => matcherArg.id === 'elgato-zeroconf-match');
  const result = await matcher!.matches({
    type: '_elg._tcp.local.',
    name: 'Office Key Light._elg._tcp.local.',
    host: 'key-light.local',
    port: 9123,
    properties: { id: 'AABBCCDDEEFF', name: 'Office Key Light' },
  }, {});

  expect(result.matched).toBeTrue();
  expect(result.candidate?.integrationDomain).toEqual('elgato');
  expect(result.candidate?.host).toEqual('key-light.local');
  expect(result.candidate?.macAddress).toEqual('aa:bb:cc:dd:ee:ff');

  const done = await (await new ElgatoConfigFlow().start(result.candidate!, {})).submit!({});
  expect(done.kind).toEqual('done');
  expect(done.config?.host).toEqual('key-light.local');
  expect(done.config?.port).toEqual(9123);
  expect(done.config?.macAddress).toEqual('aa:bb:cc:dd:ee:ff');
});

tap.test('matches DHCP registered-device Elgato candidates', async () => {
  const descriptor = createElgatoDiscoveryDescriptor();
  const matcher = descriptor.getMatchers().find((matcherArg) => matcherArg.id === 'elgato-dhcp-match');
  const result = await matcher!.matches({
    ip: '192.0.2.22',
    macaddress: 'AABBCCDDEEFF',
    hostname: 'elgato-key-light-aabbcc',
    registeredDevices: true,
  }, {});

  expect(result.matched).toBeTrue();
  expect(result.candidate?.source).toEqual('dhcp');
  expect(result.candidate?.host).toEqual('192.0.2.22');
  expect(result.candidate?.port).toEqual(9123);
  expect(result.normalizedDeviceId).toEqual('aa:bb:cc:dd:ee:ff');
});

tap.test('matches manual snapshots without requiring live HTTP', async () => {
  const rawData: Partial<IElgatoRawData> = {
    info: { productName: 'Elgato Key Light', serialNumber: 'ELG123', displayName: 'Manual Key Light', firmwareVersion: '1.0.3', firmwareBuildNumber: 42, hardwareBoardType: 7 },
    settings: { colorChangeDurationMs: 100, powerOnBehavior: 1, powerOnBrightness: 40, switchOffDurationMs: 300, switchOnDurationMs: 300 },
    state: { on: 1, brightness: 35, temperature: 200 },
  };
  const snapshot = ElgatoMapper.toSnapshot({ config: { name: 'Manual Key Light' }, rawData, online: true, source: 'manual' });
  const descriptor = createElgatoDiscoveryDescriptor();
  const manualMatcher = descriptor.getMatchers().find((matcherArg) => matcherArg.id === 'elgato-manual-match');
  const match = await manualMatcher!.matches({ name: 'Manual import', snapshot }, {});

  expect(match.matched).toBeTrue();
  expect(match.candidate?.metadata?.snapshot).toEqual(snapshot);
  const validation = await descriptor.getValidators()[0].validate(match.candidate!, {});
  expect(validation.matched).toBeTrue();

  const done = await (await new ElgatoConfigFlow().start(match.candidate!, {})).submit!({});
  expect(done.kind).toEqual('done');
  expect(done.config?.snapshot?.light.on).toBeTrue();
  expect(done.config?.snapshot?.device.serialNumber).toEqual('ELG123');
});

tap.test('rejects non-Elgato and unusable candidates', async () => {
  const descriptor = createElgatoDiscoveryDescriptor();
  const manualMatcher = descriptor.getMatchers().find((matcherArg) => matcherArg.id === 'elgato-manual-match');
  const generic = await manualMatcher!.matches({ name: 'Generic light' }, {});
  expect(generic.matched).toBeFalse();

  const validation = await descriptor.getValidators()[0].validate({ source: 'manual', name: 'Elgato without host' }, {});
  expect(validation.matched).toBeFalse();
});

export default tap.start();
