import { expect, tap } from '@git.zone/tstest/tapbundle';
import { HomekitControllerIntegration, HomekitControllerMapper } from '../../ts/integrations/homekit_controller/index.js';

const snapshot = HomekitControllerMapper.toSnapshot({
  id: 'aa:bb:cc:dd:ee:ff',
  connected: true,
  accessories: [{
    aid: 1,
    services: [{
      iid: 1,
      type: '0000003E-0000-1000-8000-0026BB765291',
      characteristics: [
        { iid: 2, type: '00000023-0000-1000-8000-0026BB765291', value: 'Living Room Bridge' },
        { iid: 3, type: '00000020-0000-1000-8000-0026BB765291', value: 'Example' },
        { iid: 4, type: '00000021-0000-1000-8000-0026BB765291', value: 'HK-Bridge' },
        { iid: 5, type: '00000030-0000-1000-8000-0026BB765291', value: 'SERIAL1' },
      ],
    }, {
      iid: 10,
      type: '00000043-0000-1000-8000-0026BB765291',
      characteristics: [
        { iid: 11, type: '00000023-0000-1000-8000-0026BB765291', value: 'Lamp' },
        { iid: 12, type: '00000025-0000-1000-8000-0026BB765291', value: true, perms: ['pr', 'pw', 'ev'] },
        { iid: 13, type: '00000008-0000-1000-8000-0026BB765291', value: 42, perms: ['pr', 'pw', 'ev'] },
      ],
    }, {
      iid: 20,
      type: '00000045-0000-1000-8000-0026BB765291',
      characteristics: [
        { iid: 21, type: '0000001D-0000-1000-8000-0026BB765291', value: 1, perms: ['pr', 'ev'] },
        { iid: 22, type: '0000001E-0000-1000-8000-0026BB765291', value: 1, perms: ['pr', 'pw', 'ev'] },
      ],
    }, {
      iid: 30,
      type: '0000008C-0000-1000-8000-0026BB765291',
      characteristics: [
        { iid: 31, type: '0000006D-0000-1000-8000-0026BB765291', value: 50, perms: ['pr', 'ev'] },
        { iid: 32, type: '0000007C-0000-1000-8000-0026BB765291', value: 50, perms: ['pr', 'pw', 'ev'] },
        { iid: 33, type: '00000072-0000-1000-8000-0026BB765291', value: 2, perms: ['pr', 'ev'] },
      ],
    }, {
      iid: 40,
      type: '00000110-0000-1000-8000-0026BB765291',
      characteristics: [
        { iid: 41, type: '000000B0-0000-1000-8000-0026BB765291', value: 1, perms: ['pr', 'pw', 'ev'] },
      ],
    }, {
      iid: 50,
      type: '00000049-0000-1000-8000-0026BB765291',
      characteristics: [
        { iid: 51, type: '00000023-0000-1000-8000-0026BB765291', value: 'Wall Switch' },
        { iid: 52, type: '00000025-0000-1000-8000-0026BB765291', value: false, perms: ['pr', 'pw', 'ev'] },
      ],
    }, {
      iid: 60,
      type: '00000047-0000-1000-8000-0026BB765291',
      characteristics: [
        { iid: 61, type: '00000023-0000-1000-8000-0026BB765291', value: 'Outlet' },
        { iid: 62, type: '00000025-0000-1000-8000-0026BB765291', value: true, perms: ['pr', 'pw', 'ev'] },
        { iid: 63, type: '00000026-0000-1000-8000-0026BB765291', value: true, perms: ['pr', 'ev'] },
      ],
    }, {
      iid: 70,
      type: '0000008A-0000-1000-8000-0026BB765291',
      characteristics: [
        { iid: 71, type: '00000011-0000-1000-8000-0026BB765291', value: 21.5, perms: ['pr', 'ev'] },
      ],
    }, {
      iid: 80,
      type: '0000004A-0000-1000-8000-0026BB765291',
      characteristics: [
        { iid: 81, type: '00000011-0000-1000-8000-0026BB765291', value: 20, perms: ['pr', 'ev'] },
        { iid: 82, type: '00000035-0000-1000-8000-0026BB765291', value: 23, perms: ['pr', 'pw', 'ev'] },
        { iid: 83, type: '00000033-0000-1000-8000-0026BB765291', value: 1, perms: ['pr', 'pw', 'ev'] },
      ],
    }, {
      iid: 90,
      type: '00000041-0000-1000-8000-0026BB765291',
      characteristics: [
        { iid: 91, type: '0000000E-0000-1000-8000-0026BB765291', value: 1, perms: ['pr', 'ev'] },
        { iid: 92, type: '00000032-0000-1000-8000-0026BB765291', value: 1, perms: ['pr', 'pw', 'ev'] },
        { iid: 93, type: '00000024-0000-1000-8000-0026BB765291', value: false, perms: ['pr', 'ev'] },
      ],
    }, {
      iid: 100,
      type: '000000B7-0000-1000-8000-0026BB765291',
      characteristics: [
        { iid: 101, type: '000000B0-0000-1000-8000-0026BB765291', value: 1, perms: ['pr', 'pw', 'ev'] },
        { iid: 102, type: '00000029-0000-1000-8000-0026BB765291', value: 55, perms: ['pr', 'pw', 'ev'] },
      ],
    }],
  }],
});

tap.test('maps HomeKit accessories to devices and entities', async () => {
  const devices = HomekitControllerMapper.toDevices(snapshot);
  const entities = HomekitControllerMapper.toEntities(snapshot);

  expect(devices[0].protocol).toEqual('homekit');
  expect(devices[0].manufacturer).toEqual('Example');
  expect(entities.some((entityArg) => entityArg.platform === 'light' && entityArg.state === 'on' && entityArg.attributes?.brightness === 42)).toBeTrue();
  expect(entities.some((entityArg) => String(entityArg.platform) === 'lock' && entityArg.state === 'locked')).toBeTrue();
  expect(entities.some((entityArg) => entityArg.platform === 'cover' && entityArg.state === 'open')).toBeTrue();
  expect(entities.some((entityArg) => String(entityArg.platform) === 'camera' && entityArg.state === 'available')).toBeTrue();
  expect(entities.some((entityArg) => entityArg.platform === 'switch' && entityArg.attributes?.serviceType === 'outlet' && entityArg.attributes?.outletInUse === true)).toBeTrue();
  expect(entities.some((entityArg) => entityArg.platform === 'sensor' && entityArg.state === 21.5)).toBeTrue();
  expect(entities.some((entityArg) => entityArg.platform === 'climate' && entityArg.state === 'heat' && entityArg.attributes?.targetTemperature === 23)).toBeTrue();
  expect(entities.some((entityArg) => entityArg.platform === 'cover' && entityArg.state === 'closed' && entityArg.attributes?.serviceType === 'garage_door_opener')).toBeTrue();
  expect(entities.some((entityArg) => entityArg.platform === 'fan' && entityArg.state === 'on' && entityArg.attributes?.percentage === 55)).toBeTrue();
});

tap.test('maps common entity services to HomeKit writes', async () => {
  const light = HomekitControllerMapper.toEntities(snapshot).find((entityArg) => entityArg.platform === 'light');
  const command = HomekitControllerMapper.commandForService(snapshot, {
    domain: 'light',
    service: 'turn_off',
    target: { entityId: light?.id },
  });

  expect(command?.command).toEqual('write_characteristics');
  expect(command?.writes?.[0]?.aid).toEqual(1);
  expect(command?.writes?.[0]?.iid).toEqual(12);
  expect(command?.writes?.[0]?.value).toEqual(false);

  const lightOnCommand = HomekitControllerMapper.commandForService(snapshot, {
    domain: 'light',
    service: 'turn_on',
    target: { entityId: light?.id },
    data: { brightness: 128 },
  });
  expect(lightOnCommand?.writes?.some((writeArg) => writeArg.iid === 13 && writeArg.value === 50)).toBeTrue();

  const fan = HomekitControllerMapper.toEntities(snapshot).find((entityArg) => entityArg.platform === 'fan');
  const fanCommand = HomekitControllerMapper.commandForService(snapshot, {
    domain: 'fan',
    service: 'set_percentage',
    target: { entityId: fan?.id },
    data: { percentage: 75 },
  });
  expect(fanCommand?.writes?.some((writeArg) => writeArg.iid === 102 && writeArg.value === 75)).toBeTrue();

  const climate = HomekitControllerMapper.toEntities(snapshot).find((entityArg) => entityArg.platform === 'climate');
  const climateCommand = HomekitControllerMapper.commandForService(snapshot, {
    domain: 'climate',
    service: 'set_hvac_mode',
    target: { entityId: climate?.id },
    data: { hvac_mode: 'heat_cool' },
  });
  expect(climateCommand?.writes?.some((writeArg) => writeArg.iid === 83 && writeArg.value === 3)).toBeTrue();

  const camera = HomekitControllerMapper.toEntities(snapshot).find((entityArg) => String(entityArg.platform) === 'camera');
  const cameraCommand = HomekitControllerMapper.commandForService(snapshot, {
    domain: 'camera',
    service: 'snapshot',
    target: { entityId: camera?.id },
    data: { width: 320, height: 240 },
  });
  expect(cameraCommand?.command).toEqual('camera_snapshot');
  expect(cameraCommand?.aid).toEqual(1);
});

tap.test('returns explicit unsupported errors for native HAP security operations', async () => {
  const integration = new HomekitControllerIntegration();
  const runtime = await integration.setup({ host: 'desk-lamp.local', setupCode: '234-56-789' }, {});
  const result = await runtime.callService?.({
    domain: 'homekit_controller',
    service: 'pair_setup',
    target: {},
  });

  expect(result?.success).toEqual(false);
  expect(String(result?.error).includes('pair setup is not implemented')).toBeTrue();
  await runtime.destroy();
});

export default tap.start();
