import { expect, tap } from '@git.zone/tstest/tapbundle';
import { ModbusClient, ModbusMapper, type IModbusConfig } from '../../ts/integrations/modbus/index.js';

const config: IModbusConfig = {
  hubs: [{
    name: 'plant_hub',
    type: 'tcp',
    host: '192.168.1.50',
    port: 502,
    registers: [{
      name: 'Supply Temp',
      address: 100,
      slave: 2,
      dataType: 'int16',
      registers: [215],
      scale: 0.1,
      precision: 1,
      unitOfMeasurement: 'C',
    }],
    numbers: [{
      name: 'Setpoint',
      address: 101,
      slave: 2,
      dataType: 'uint16',
      value: 22,
      min: 10,
      max: 30,
      step: 0.5,
      writable: true,
    }],
    coils: [{
      name: 'Pump Running',
      address: 5,
      slave: 2,
      value: true,
    }],
    switches: [{
      name: 'Pump Enable',
      address: 6,
      slave: 2,
      writeType: 'coil',
      value: false,
      commandOn: 1,
      commandOff: 0,
    }],
  }],
};

tap.test('maps configured Modbus registers and coils to devices and entities', async () => {
  const snapshot = await new ModbusClient(config).getSnapshot();
  const devices = ModbusMapper.toDevices(snapshot);
  const entities = ModbusMapper.toEntities(snapshot);

  expect(devices.some((deviceArg) => deviceArg.id === 'modbus.hub.plant_hub')).toBeTrue();
  expect(devices.some((deviceArg) => deviceArg.id === 'modbus.slave.plant_hub.2')).toBeTrue();
  expect(entities.find((entityArg) => entityArg.id === 'sensor.supply_temp')?.state).toEqual(21.5);
  expect(entities.find((entityArg) => entityArg.id === 'binary_sensor.pump_running')?.state).toEqual('on');
  expect(entities.find((entityArg) => entityArg.id === 'switch.pump_enable')?.state).toEqual('off');
  expect(entities.find((entityArg) => entityArg.id === 'number.setpoint')?.state).toEqual(22);
});

tap.test('maps Modbus services to coil and register commands', async () => {
  const snapshot = await new ModbusClient(config).getSnapshot();
  const switchCommand = ModbusMapper.commandForService(snapshot, {
    domain: 'switch',
    service: 'turn_on',
    target: { entityId: 'switch.pump_enable' },
  });
  expect(switchCommand).toEqual({
    type: 'write_coil',
    hub: 'plant_hub',
    hubId: 'plant_hub',
    unitId: 2,
    entityId: 'switch.pump_enable',
    deviceId: undefined,
    uniqueId: 'modbus_plant_hub_slave_2_switch_6',
    address: 6,
    value: 1,
  });

  const readCommand = ModbusMapper.commandForService(snapshot, {
    domain: 'modbus',
    service: 'read_register',
    target: {},
    data: { hub: 'plant_hub', slave: 2, address: 100, count: 1, inputType: 'holding' },
  });
  expect(readCommand).toEqual({
    type: 'read_register',
    hub: 'plant_hub',
    hubId: 'plant_hub',
    unitId: 2,
    entityId: undefined,
    deviceId: undefined,
    uniqueId: undefined,
    address: 100,
    count: 1,
    inputType: 'holding',
    dataType: undefined,
  });
});

export default tap.start();
