import { expect, tap } from '@git.zone/tstest/tapbundle';
import { MatterMapper } from '../../ts/integrations/matter/index.js';
import type { IMatterSnapshot } from '../../ts/integrations/matter/index.js';

const snapshot: IMatterSnapshot = {
  connected: true,
  events: [],
  serverInfo: {
    fabric_id: 1,
    compressed_fabric_id: 2,
    schema_version: 11,
    min_supported_schema_version: 6,
    sdk_version: '1.4.2',
    wifi_credentials_set: true,
    thread_credentials_set: false,
    bluetooth_enabled: false,
  },
  nodes: [{
    node_id: 1234,
    available: true,
    attributes: {
      '0/29/0': [{ deviceType: 0x0016, revision: 1 }],
      '0/29/1': [29, 40],
      '0/40/1': 'Acme',
      '0/40/2': 123,
      '0/40/3': 'Matter Test Device',
      '0/40/4': 456,
      '0/40/5': 'Test Node',
      '0/40/15': 'serial-1',
      '1/29/0': [{ deviceType: 0x0101, revision: 2 }],
      '1/29/1': [29, 6, 8],
      '1/6/0': true,
      '1/8/0': 128,
      '1/8/2': 1,
      '1/8/3': 254,
      '2/29/0': [{ deviceType: 0x0015, revision: 1 }],
      '2/29/1': [29, 69],
      '2/69/0': false,
      '3/29/0': [{ deviceType: 0x0202, revision: 1 }],
      '3/29/1': [29, 258],
      '3/258/10': 0,
      '3/258/14': 2500,
      '4/29/0': [{ deviceType: 0x000a, revision: 1 }],
      '4/29/1': [29, 257],
      '4/257/0': 1,
      '5/29/0': [{ deviceType: 0x0301, revision: 1 }],
      '5/29/1': [29, 513],
      '5/513/0': 2150,
      '5/513/18': 2000,
      '5/513/28': 4,
    },
  }],
};

tap.test('maps Matter nodes to canonical devices and entities', async () => {
  const devices = MatterMapper.toDevices(snapshot);
  const entities = MatterMapper.toEntities(snapshot);

  expect(devices.some((deviceArg) => deviceArg.id === 'matter.node.1234.endpoint.1')).toBeTrue();
  expect(entities.some((entityArg) => entityArg.platform === 'light' && entityArg.state === 'on')).toBeTrue();
  expect(entities.some((entityArg) => entityArg.platform === 'binary_sensor' && entityArg.attributes?.deviceClass === 'door')).toBeTrue();
  expect(entities.some((entityArg) => entityArg.platform === 'cover' && entityArg.attributes?.position === 75)).toBeTrue();
  expect(entities.some((entityArg) => String(entityArg.platform) === 'lock' && entityArg.state === 'locked')).toBeTrue();
  expect(entities.some((entityArg) => entityArg.platform === 'climate' && entityArg.state === 'heat')).toBeTrue();
});

tap.test('maps entity services to Matter server commands', async () => {
  const light = MatterMapper.toEntities(snapshot).find((entityArg) => entityArg.platform === 'light');
  const cover = MatterMapper.toEntities(snapshot).find((entityArg) => entityArg.platform === 'cover');

  const turnOff = MatterMapper.commandForService(snapshot, {
    domain: 'light',
    service: 'turn_off',
    target: { entityId: light?.id },
  });
  const setPosition = MatterMapper.commandForService(snapshot, {
    domain: 'cover',
    service: 'set_position',
    target: { entityId: cover?.id },
    data: { position: 42 },
  });

  expect(turnOff?.command).toEqual('device_command');
  expect(turnOff?.args?.cluster_id).toEqual(6);
  expect(turnOff?.args?.command_name).toEqual('Off');
  expect(setPosition?.args?.cluster_id).toEqual(258);
  expect(setPosition?.args?.payload).toEqual({ liftPercent100thsValue: 5800 });
});

export default tap.start();
