import { expect, tap } from '@git.zone/tstest/tapbundle';
import { SynologySrmMapper, type ISynologySrmSnapshot } from '../../ts/integrations/synology_srm/index.js';

const snapshot: ISynologySrmSnapshot = {
  connected: true,
  updatedAt: '2026-01-01T00:00:00.000Z',
  router: {
    host: '192.168.1.1',
    port: 8001,
    ssl: true,
    name: 'RT6600ax',
    model: 'RT6600ax',
    macAddress: 'AA:BB:CC:DD:EE:FF',
    actions: ['reboot'],
  },
  system: {
    versionString: 'SRM 1.3.1',
    cpuLoad: 21,
    memoryUsage: 45,
    uptimeSeconds: 7200,
  },
  network: {
    wanIp: '203.0.113.10',
    macs: ['AA:BB:CC:DD:EE:FF'],
  },
  interfaces: [
    {
      name: 'wan',
      label: 'WAN',
      connected: true,
      rxBytes: 4_000,
      txBytes: 2_000,
      rxRate: 64,
      txRate: 32,
    },
  ],
  clients: [
    {
      mac: '11:22:33:44:55:66',
      hostname: 'Kitchen Phone',
      ip_addr: '192.168.1.40',
      ip6_addr: 'fe80::1',
      is_online: true,
      is_wireless: true,
      is_guest: false,
      is_baned: false,
      is_parental_controled: true,
      signalstrength: -51,
      transferRXRate: 1024,
      transferTXRate: 512,
    },
  ],
  traffic: {},
  sensors: {
    temperature: 43,
  },
  switches: [
    { key: 'guest_wifi', name: 'Guest Wi-Fi', enabled: true, target: 'router', action: 'set_switch_enabled' },
  ],
  actions: [],
};

tap.test('maps Synology SRM router, system, network, interfaces, clients, traffic, sensors, and switches', async () => {
  const normalized = SynologySrmMapper.toSnapshot({ snapshot });
  const devices = SynologySrmMapper.toDevices(normalized);
  const entities = SynologySrmMapper.toEntities(normalized);

  expect(normalized.clients[0].ipAddress).toEqual('192.168.1.40');
  expect(normalized.clients[0].banned).toBeFalse();
  expect(normalized.clients[0].parentalControlled).toBeTrue();
  expect(normalized.sensors.downloadRate).toEqual(64);
  expect(devices.some((deviceArg) => deviceArg.id === 'synology_srm.router.aa_bb_cc_dd_ee_ff')).toBeTrue();
  expect(devices.some((deviceArg) => deviceArg.id === 'synology_srm.client.11_22_33_44_55_66')).toBeTrue();
  expect(entities.find((entityArg) => entityArg.id === 'sensor.rt6600ax_download_speed')?.state).toEqual(64);
  expect(entities.find((entityArg) => entityArg.id === 'sensor.rt6600ax_wan_upload_speed')?.state).toEqual(32);
  expect(entities.find((entityArg) => entityArg.id === 'binary_sensor.kitchen_phone_connected')?.attributes?.is_banned).toBeFalse();
  expect(entities.find((entityArg) => entityArg.id === 'sensor.kitchen_phone_signal_strength')?.state).toEqual(-51);
  expect(entities.find((entityArg) => entityArg.id === 'switch.kitchen_phone_network_access')?.state).toEqual('on');
  expect(entities.find((entityArg) => entityArg.id === 'switch.kitchen_phone_parental_control')?.state).toEqual('on');
  expect(entities.find((entityArg) => entityArg.id === 'switch.guest_wi_fi')?.attributes?.nativeAction).toEqual('set_switch_enabled');
});

tap.test('models represented Synology SRM commands without executing them', async () => {
  const normalized = SynologySrmMapper.toSnapshot({ snapshot });
  const rebootCommand = SynologySrmMapper.commandForService(normalized, {
    domain: 'synology_srm',
    service: 'reboot',
    target: {},
  });
  const blockCommand = SynologySrmMapper.commandForService(normalized, {
    domain: 'synology_srm',
    service: 'block_client',
    target: {},
    data: { mac: '11-22-33-44-55-66' },
  });
  const networkAccessCommand = SynologySrmMapper.commandForService(normalized, {
    domain: 'switch',
    service: 'turn_off',
    target: { entityId: 'switch.kitchen_phone_network_access' },
  });
  const unsupportedClient = SynologySrmMapper.commandForService(normalized, {
    domain: 'synology_srm',
    service: 'block_client',
    target: {},
    data: { mac: 'AA:AA:AA:AA:AA:AA' },
  });

  expect(rebootCommand?.type).toEqual('router.action');
  expect(blockCommand?.action).toEqual('set_client_blocked');
  expect(blockCommand?.mac).toEqual('11:22:33:44:55:66');
  expect(networkAccessCommand?.type).toEqual('switch.set');
  expect(networkAccessCommand?.payload?.blocked).toBeTrue();
  expect(unsupportedClient).toBeUndefined();
});

export default tap.start();
