import { describe, it, expect } from 'vitest';
import {
  SCRIPTS,
  listScripts,
  getScript,
  parseJsonOutput,
} from './index';

describe('RMM script registry', () => {
  it('contains the v1 + LogLift scripts', () => {
    expect(Object.keys(SCRIPTS).sort()).toEqual([
      'get-ad-health',
      'get-dhcp-scopes',
      'get-dns-zones',
      'get-event-log-recent',
      'get-installed-software',
      'get-network-discovery',
      'get-services',
      'loglift-eventlogs',
    ]);
  });

  it('all scripts have required fields', () => {
    for (const s of Object.values(SCRIPTS)) {
      expect(s.id).toBeTruthy();
      expect(s.name).toBeTruthy();
      expect(s.description).toBeTruthy();
      expect(['site_anchor', 'asset_self']).toContain(s.target_type);
      // Overshell scripts carry the body; b2_upload scripts deploy the
      // body externally as a Datto component, so we don't require it.
      if (s.transport === 'b2_upload') {
        expect(s.body).toBe('');
      } else {
        expect(s.body.length).toBeGreaterThan(50);
      }
      expect(typeof s.parseOutput).toBe('function');
      expect(s.expected_runtime_seconds).toBeGreaterThan(0);
      expect(s.expected_runtime_seconds).toBeLessThan(300); // safety check
      expect(s.version).toBeGreaterThanOrEqual(1);
    }
  });

  it('listScripts returns sorted list', () => {
    const list = listScripts();
    const names = list.map((s) => s.name);
    expect(names).toEqual([...names].sort());
  });

  it('getScript returns null on unknown id', () => {
    expect(getScript('does-not-exist')).toBeNull();
    expect(getScript('get-services')?.id).toBe('get-services');
  });

  it('script bodies do not contain credential patterns', () => {
    // Heuristic: no script should reference plaintext password handling.
    for (const s of Object.values(SCRIPTS)) {
      const lower = s.body.toLowerCase();
      expect(lower).not.toMatch(/\$plain.*password/);
      expect(lower).not.toMatch(/-asplaintext/);
    }
  });
});

describe('parseJsonOutput', () => {
  it('parses clean JSON', () => {
    expect(parseJsonOutput('{"ok":true}')).toEqual({ ok: true });
    expect(parseJsonOutput('[1,2,3]')).toEqual([1, 2, 3]);
  });

  it('strips a leading banner before the JSON', () => {
    expect(
      parseJsonOutput('Datto Quick Job Output:\n{"ok":true,"value":42}')
    ).toEqual({ ok: true, value: 42 });
  });

  it('throws when there is no JSON', () => {
    expect(() => parseJsonOutput('')).toThrow();
    expect(() => parseJsonOutput('Just text, no braces.')).toThrow();
  });
});
