import { expect, tap } from '@git.zone/tstest/tapbundle';
import { OpnsenseMapper, type IOpnsenseSnapshot } from '../../ts/integrations/opnsense/index.js';

const snapshot: IOpnsenseSnapshot = {
  connected: true,
  updatedAt: '2026-01-01T00:00:00.000Z',
  router: {
    host: '192.168.1.1',
    name: 'Edge Firewall',
    macAddress: 'AA:BB:CC:DD:EE:FF',
    firmware: '25.7',
    latestFirmware: '26.1',
    updateAvailable: true,
    actions: ['reboot', 'firmware_update'],
  },
  devices: [],
  interfaces: [
    {
      name: 'wan',
      label: 'WAN',
      status: 'up',
      inbytes: 2_000_000_000,
      outbytes: 1_000_000_000,
      inpkts: 100,
      outpkts: 50,
      actions: ['reload'],
    },
  ],
  gateways: [
    { name: 'WAN_DHCP', status: 'online', latency: '4.1 ms', loss: '0.0 %', interface: 'wan' },
  ],
  firewall: {
    rules: [{ uuid: 'rule-1', description: 'Allow LAN', enabled: true, interface: 'lan', protocol: 'tcp' }],
    nat: { d_nat: [{ uuid: 'nat-1', description: 'HTTPS', disabled: '0', protocol: 'tcp' }] },
    aliases: [{ uuid: 'alias-1', name: 'BlockedHosts', enabled: false, type: 'host' }],
    state: { used: 42, total: 100, usedPercent: 42 },
  },
  system: {
    firmwareVersion: '25.7',
    productLatest: '26.1',
    updateAvailable: true,
    pendingNoticesPresent: true,
    pendingNotices: [{ id: 'notice1', notice: 'Reboot required' }],
  },
  telemetry: {
    cpu: { usage_total: 12 },
    memory: { used_percent: 34 },
    mbuf: { used_percent: 5 },
  },
  services: [
    { name: 'unbound', displayName: 'Unbound DNS', running: 1 },
  ],
  vpn: {
    openvpn: { servers: [{ uuid: 'ovpn1', name: 'Remote Access', enabled: true, connected_clients: 2 }] },
    wireguard: { clients: [{ uuid: 'wgclient1', name: 'Mullvad', enabled: false, connected_servers: 0 }] },
  },
  sensors: {},
  switches: [
    { id: 'dnsbl', name: 'Unbound DNSBL', enabled: true, nativeType: 'unbound_blocklist', uuid: 'dnsbl-1' },
  ],
  actions: [],
};

tap.test('maps OPNsense snapshot sections and HA ARP tracker filtering', async () => {
  const normalized = OpnsenseMapper.toSnapshot({
    snapshot,
    trackerInterfaces: ['LAN'],
    arpTable: [
      { 'mac-address': '11:22:33:44:55:66', 'ip-address': '192.168.1.20', hostname: 'Kitchen Phone', intf_description: 'LAN', manufacturer: 'PhoneCo' },
      { 'mac-address': '22:33:44:55:66:77', 'ip-address': '192.168.1.21', hostname: 'WAN Host', intf_description: 'WAN' },
    ],
  });
  const devices = OpnsenseMapper.toDevices(normalized);
  const entities = OpnsenseMapper.toEntities(normalized);

  expect(devices.some((deviceArg) => deviceArg.id === 'opnsense.router.aa_bb_cc_dd_ee_ff')).toBeTrue();
  expect(devices.some((deviceArg) => deviceArg.id === 'opnsense.client.11_22_33_44_55_66')).toBeTrue();
  expect(devices.some((deviceArg) => deviceArg.id === 'opnsense.client.22_33_44_55_66_77')).toBeFalse();
  expect(entities.find((entityArg) => entityArg.id === 'sensor.edge_firewall_cpu_usage')?.state).toEqual(12);
  expect(entities.find((entityArg) => entityArg.id === 'sensor.edge_firewall_memory_usage')?.state).toEqual(34);
  expect(entities.find((entityArg) => entityArg.id === 'sensor.edge_firewall_firewall_state_table_used')?.state).toEqual(42);
  expect(entities.find((entityArg) => entityArg.id === 'sensor.edge_firewall_wan_download')?.state).toEqual(2);
  expect(entities.find((entityArg) => entityArg.id === 'binary_sensor.edge_firewall_gateway_wan_dhcp')?.state).toEqual('on');
  expect(entities.find((entityArg) => entityArg.id === 'binary_sensor.kitchen_phone_connected')?.attributes?.nativePlatform).toEqual('device_tracker');
  expect(entities.find((entityArg) => entityArg.id === 'switch.edge_firewall_firewall_allow_lan')?.state).toEqual('on');
  expect(entities.find((entityArg) => entityArg.id === 'switch.unbound_dns_service')?.state).toEqual('on');
  expect(entities.find((entityArg) => entityArg.id === 'switch.edge_firewall_openvpn_remote_access')?.state).toEqual('on');
  expect(entities.find((entityArg) => entityArg.id === 'update.edge_firewall_firmware')?.attributes?.latestVersion).toEqual('26.1');
});

tap.test('models safe OPNsense commands only for represented resources', async () => {
  const normalized = OpnsenseMapper.toSnapshot({ snapshot });
  const serviceCommand = OpnsenseMapper.commandForService(normalized, {
    domain: 'switch',
    service: 'turn_off',
    target: { entityId: 'switch.unbound_dns_service' },
  });
  const firewallCommand = OpnsenseMapper.commandForService(normalized, {
    domain: 'switch',
    service: 'turn_off',
    target: { entityId: 'switch.edge_firewall_firewall_allow_lan' },
  });
  const natCommand = OpnsenseMapper.commandForService(normalized, {
    domain: 'switch',
    service: 'turn_off',
    target: { entityId: 'switch.edge_firewall_nat_https' },
  });
  const rebootCommand = OpnsenseMapper.commandForService(normalized, {
    domain: 'opnsense',
    service: 'reboot',
    target: {},
  });
  const missingServiceCommand = OpnsenseMapper.commandForService(normalized, {
    domain: 'opnsense',
    service: 'stop_service',
    target: {},
    data: { service: 'missing' },
  });

  expect(serviceCommand && !('error' in serviceCommand) ? serviceCommand.path : '').toEqual('/api/core/service/stop/unbound');
  expect(firewallCommand && !('error' in firewallCommand) ? firewallCommand.path : '').toEqual('/api/firewall/filter/toggle_rule/rule-1/0');
  expect(natCommand && !('error' in natCommand) ? natCommand.path : '').toEqual('/api/firewall/d_nat/toggle_rule/nat-1/1');
  expect(rebootCommand && !('error' in rebootCommand) ? rebootCommand.type : '').toEqual('router.action');
  expect(missingServiceCommand).toBeUndefined();
});

export default tap.start();
