import { tap, expect } from '@git.zone/tstest/tapbundle';
import { IPReputationChecker, ReputationThreshold } from '../ts/security/classes.ipreputationchecker.js';
import { RustSecurityBridge } from '../ts/security/classes.rustsecuritybridge.js';

let bridge: RustSecurityBridge;

// Start the Rust bridge before tests
tap.test('setup - start Rust security bridge', async () => {
  bridge = RustSecurityBridge.getInstance();
  const ok = await bridge.start();
  expect(ok).toEqual(true);
});

// Test instantiation
tap.test('IPReputationChecker - should be instantiable', async () => {
  const checker = IPReputationChecker.getInstance({
    enableLocalCache: false
  });

  expect(checker).toBeTruthy();
});

// Test singleton pattern
tap.test('IPReputationChecker - should use singleton pattern', async () => {
  const checker1 = IPReputationChecker.getInstance();
  const checker2 = IPReputationChecker.getInstance();

  expect(checker1 === checker2).toEqual(true);
});

// Test IP validation
tap.test('IPReputationChecker - should validate IP address format', async () => {
  const checker = IPReputationChecker.getInstance();

  // Invalid IP should fail with error
  const invalidResult = await checker.checkReputation('invalid.ip');
  expect(invalidResult.error).toBeTruthy();
});

// Test reputation check via Rust bridge
tap.test('IPReputationChecker - should check IP reputation via Rust', async () => {
  const testInstance = new IPReputationChecker({
    enableLocalCache: false,
    maxCacheSize: 10
  });

  // Check a public IP (Google DNS) — should get a result with a score
  const result = await testInstance.checkReputation('8.8.8.8');
  expect(result).toBeTruthy();
  expect(result.score).toBeGreaterThan(0);
  expect(result.score).toBeLessThanOrEqual(100);
  expect(typeof result.isSpam).toEqual('boolean');
  expect(typeof result.isProxy).toEqual('boolean');
  expect(typeof result.isTor).toEqual('boolean');
  expect(typeof result.isVPN).toEqual('boolean');
  expect(result.timestamp).toBeGreaterThan(0);
});

// Test caching behavior
tap.test('IPReputationChecker - should cache reputation results', async () => {
  const testInstance = new IPReputationChecker({
    enableLocalCache: false,
    maxCacheSize: 10
  });

  const ip = '1.1.1.1';

  // First check should add to cache
  const result1 = await testInstance.checkReputation(ip);
  expect(result1).toBeTruthy();

  // Verify it's in cache
  const hasInCache = (testInstance as any).reputationCache.has(ip);
  expect(hasInCache).toEqual(true);

  // Call again, should use cache
  const result2 = await testInstance.checkReputation(ip);
  expect(result2).toBeTruthy();

  // Results should be identical (from cache)
  expect(result1.score).toEqual(result2.score);
  expect(result1.isSpam).toEqual(result2.isSpam);
});

// Test risk level classification
tap.test('IPReputationChecker - should classify risk levels correctly', async () => {
  expect(IPReputationChecker.getRiskLevel(10)).toEqual('high');
  expect(IPReputationChecker.getRiskLevel(30)).toEqual('medium');
  expect(IPReputationChecker.getRiskLevel(60)).toEqual('low');
  expect(IPReputationChecker.getRiskLevel(90)).toEqual('trusted');
});

// Test error handling for error result
tap.test('IPReputationChecker - should handle errors gracefully', async () => {
  const testInstance = new IPReputationChecker({
    enableLocalCache: false,
    maxCacheSize: 5
  });

  // Invalid format should return error result with neutral score
  const result = await testInstance.checkReputation('not-an-ip');
  expect(result.score).toEqual(50);
  expect(result.error).toBeTruthy();
  expect(result.isSpam).toEqual(false);
});

// Stop bridge
tap.test('cleanup - stop Rust security bridge', async () => {
  await bridge.stop();
});

tap.test('stop', async () => {
  await tap.stopForcefully();
});

export default tap.start();
