// tests/detectors.test.js

require('../__mocks__/chrome.js');
const { detectViolations, DETECTOR_NAMES } = require('../lib/detectors.js');

describe('Detectors', () => {
  beforeEach(() => {
    global.__chromeStore = {};
  });

  test('DETECTOR_NAMES has 6 detectors', () => {
    expect(DETECTOR_NAMES).toHaveLength(6);
    expect(DETECTOR_NAMES).toContain('permission_bypass');
    expect(DETECTOR_NAMES).toContain('out_of_scope');
    expect(DETECTOR_NAMES).toContain('self_permissioning');
    expect(DETECTOR_NAMES).toContain('disallowed_tools');
    expect(DETECTOR_NAMES).toContain('redundant_operations');
    expect(DETECTOR_NAMES).toContain('off_task');
  });

  test('detects permission bypass for disallowed domain', async () => {
    const event = {
      id: 'evt-1',
      type: 'api_call',
      tool: 'fetch',
      target: 'https://malicious.com/api',
      url: 'https://claude.ai/chat',
      timestamp: new Date().toISOString()
    };
    const policy = {
      rules: [
        { id: 'rule_allowed_domains', type: 'allowed_domains', enabled: true, params: { domains: ['github.com', 'claude.ai'] } }
      ]
    };
    const violations = await detectViolations(event, policy);
    const bypass = violations.find(v => v.detector === 'permission_bypass');
    expect(bypass).toBeDefined();
    expect(bypass.severity).toBe('high');
    expect(bypass.message).toContain('malicious.com');
  });

  test('allows permitted domain', async () => {
    const event = {
      id: 'evt-2',
      type: 'api_call',
      tool: 'fetch',
      target: 'https://github.com/api',
      url: 'https://claude.ai/chat',
      timestamp: new Date().toISOString()
    };
    const policy = {
      rules: [
        { id: 'rule_allowed_domains', type: 'allowed_domains', enabled: true, params: { domains: ['github.com'] } }
      ]
    };
    const violations = await detectViolations(event, policy);
    const bypass = violations.find(v => v.detector === 'permission_bypass');
    expect(bypass).toBeUndefined();
  });

  test('detects disallowed tools', async () => {
    const event = {
      id: 'evt-3',
      type: 'tool_use',
      tool: 'eval',
      target: 'some-script.js',
      url: 'https://claude.ai/chat',
      timestamp: new Date().toISOString()
    };
    const policy = {
      rules: [
        { id: 'rule_disallowed_tools', type: 'disallowed_tools', enabled: true, params: { tools: ['eval', 'exec'] } }
      ]
    };
    const violations = await detectViolations(event, policy);
    const disallowed = violations.find(v => v.detector === 'disallowed_tools');
    expect(disallowed).toBeDefined();
    expect(disallowed.severity).toBe('critical');
    expect(disallowed.message).toContain('eval');
  });

  test('detects self-permissioning', async () => {
    const event = {
      id: 'evt-4',
      type: 'tool_use',
      tool: 'edit_file',
      target: 'permissions.json',
      context: 'grant admin access control role privilege',
      url: 'https://claude.ai/chat',
      timestamp: new Date().toISOString()
    };
    const policy = {
      rules: [
        { id: 'rule_permission_change', type: 'permission_change', enabled: true, params: {} }
      ]
    };
    const violations = await detectViolations(event, policy);
    const perm = violations.find(v => v.detector === 'self_permissioning');
    expect(perm).toBeDefined();
    expect(perm.severity).toBe('critical');
  });

  test('detects out-of-scope operations', async () => {
    const event = {
      id: 'evt-5',
      type: 'api_call',
      tool: 'delete',
      target: 'https://api.example.com/resource',
      url: 'https://claude.ai/chat',
      timestamp: new Date().toISOString()
    };
    const policy = {
      rules: [
        { id: 'rule_allowed_operations', type: 'allowed_operations', enabled: true, params: { operations: ['read', 'chat'] } }
      ]
    };
    const violations = await detectViolations(event, policy);
    const scope = violations.find(v => v.detector === 'out_of_scope');
    expect(scope).toBeDefined();
    expect(scope.severity).toBe('medium');
  });

  test('no violations for normal activity', async () => {
    const event = {
      id: 'evt-6',
      type: 'chat',
      tool: 'chat',
      target: 'conversation',
      url: 'https://claude.ai/chat',
      timestamp: new Date().toISOString()
    };
    const policy = {
      rules: [
        { id: 'rule_allowed_domains', type: 'allowed_domains', enabled: true, params: { domains: ['claude.ai'] } },
        { id: 'rule_disallowed_tools', type: 'disallowed_tools', enabled: true, params: { tools: ['eval'] } }
      ]
    };
    const violations = await detectViolations(event, policy);
    expect(violations).toHaveLength(0);
  });
});
