import { expect, tap } from '@git.zone/tstest/tapbundle';
import { CiscoIosIntegration, type ICiscoIosCommand, type ICiscoIosCommandResult } from '../../ts/integrations/cisco_ios/index.js';

const arpOutput = `Protocol  Address          Age (min)  Hardware Addr   Type   Interface
Internet  10.10.11.20      0          001d.ec02.07ab  ARPA   Vlan1
`;

tap.test('does not fake Cisco IOS CLI command success without injected transport', async () => {
  const runtime = await new CiscoIosIntegration().setup({ name: 'Static Router', arpOutput }, {});
  const snapshotResult = await runtime.callService?.({ domain: 'cisco_ios', service: 'snapshot', target: {}, data: {} });
  const commandResult = await runtime.callService?.({ domain: 'cisco_ios', service: 'show_ip_arp', target: {}, data: {} });

  expect(snapshotResult?.success).toBeTrue();
  expect(commandResult?.success).toBeFalse();
  expect(commandResult?.error || '').toContain('require an injected');
  await runtime.destroy();
});

tap.test('refreshes Cisco IOS snapshots through an injected command executor', async () => {
  const commands: ICiscoIosCommand[] = [];
  const runtime = await new CiscoIosIntegration().setup({
    host: '192.168.1.1',
    username: 'admin',
    commandExecutor: async (commandArg) => {
      commands.push(commandArg);
      return commandArg.command === 'show ip arp' ? arpOutput : { success: true };
    },
  }, {});

  const refresh = await runtime.callService?.({ domain: 'cisco_ios', service: 'refresh', target: {}, data: {} }) as ICiscoIosCommandResult | undefined;
  const snapshotResult = await runtime.callService?.({ domain: 'cisco_ios', service: 'snapshot', target: {}, data: {} });
  const snapshot = snapshotResult?.data as { source?: string; trackedDevices?: unknown[] } | undefined;

  expect(refresh?.success).toBeTrue();
  expect(refresh?.transmitted).toBeTrue();
  expect(snapshot?.source).toEqual('executor');
  expect(snapshot?.trackedDevices?.length).toEqual(1);
  expect(commands.some((commandArg) => commandArg.command === 'terminal length 0')).toBeTrue();
  expect(commands.some((commandArg) => commandArg.command === 'show ip arp')).toBeTrue();
  await runtime.destroy();
});

tap.test('delegates explicit Cisco IOS run_command service to an injected executor', async () => {
  let command: ICiscoIosCommand | undefined;
  const runtime = await new CiscoIosIntegration().setup({
    name: 'Executor Router',
    arpOutput,
    commandExecutor: async (commandArg) => {
      command = commandArg;
      return { success: true, output: 'Cisco IOS Software' };
    },
  }, {});

  const result = await runtime.callService?.({ domain: 'cisco_ios', service: 'run_command', target: {}, data: { command: 'show version' } });
  expect(result?.success).toBeTrue();
  expect(command?.command).toEqual('show version');
  await runtime.destroy();
});

export default tap.start();
