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

let bridge: RustSecurityBridge;

tap.test('RustSecurityBridge - should get singleton instance', async () => {
  bridge = RustSecurityBridge.getInstance();
  expect(bridge).toBeTruthy();
  expect(bridge).toEqual(RustSecurityBridge.getInstance()); // same instance
});

tap.test('RustSecurityBridge - should start the Rust binary', async () => {
  const ok = await bridge.start();
  if (!ok) {
    console.log('WARNING: Rust binary not available — skipping bridge tests');
    console.log('Build it with: cd rust && cargo build --release');
  }
  // We accept both true and false — the binary may not be built yet
  expect(typeof ok).toEqual('boolean');
});

tap.test('RustSecurityBridge - ping should return pong', async () => {
  if (!bridge.running) {
    console.log('SKIP: bridge not running');
    return;
  }
  const pong = await bridge.ping();
  expect(pong).toBeTrue();
});

tap.test('RustSecurityBridge - version should return crate versions', async () => {
  if (!bridge.running) {
    console.log('SKIP: bridge not running');
    return;
  }
  const version = await bridge.getVersion();
  expect(version.bin).toBeTruthy();
  expect(version.core).toBeTruthy();
  expect(version.security).toBeTruthy();
});

tap.test('RustSecurityBridge - validateEmail with valid address', async () => {
  if (!bridge.running) {
    console.log('SKIP: bridge not running');
    return;
  }
  const result = await bridge.validateEmail('test@example.com');
  expect(result.valid).toBeTrue();
  expect(result.formatValid).toBeTrue();
});

tap.test('RustSecurityBridge - validateEmail with invalid address', async () => {
  if (!bridge.running) {
    console.log('SKIP: bridge not running');
    return;
  }
  const result = await bridge.validateEmail('not-an-email');
  expect(result.formatValid).toBeFalse();
});

tap.test('RustSecurityBridge - detectBounce with known SMTP response', async () => {
  if (!bridge.running) {
    console.log('SKIP: bridge not running');
    return;
  }
  const result = await bridge.detectBounce({
    smtpResponse: '550 5.1.1 User unknown',
  });
  expect(result.bounce_type).toBeTruthy();
  expect(result.category).toBeTruthy();
});

tap.test('RustSecurityBridge - checkIpReputation', async () => {
  if (!bridge.running) {
    console.log('SKIP: bridge not running');
    return;
  }
  // Use a well-known IP that should NOT be on blacklists
  const result = await bridge.checkIpReputation('8.8.8.8');
  expect(result.ip).toEqual('8.8.8.8');
  expect(typeof result.score).toEqual('number');
  expect(result.score).toBeGreaterThan(0);
});

tap.test('RustSecurityBridge - verifyDkim with unsigned message', async () => {
  if (!bridge.running) {
    console.log('SKIP: bridge not running');
    return;
  }
  const rawMessage = 'From: test@example.com\r\nTo: receiver@example.com\r\nSubject: Test\r\n\r\nHello';
  const results = await bridge.verifyDkim(rawMessage);
  expect(results.length).toBeGreaterThan(0);
  expect(results[0].status).toEqual('none'); // no DKIM signature
});

tap.test('RustSecurityBridge - verifyEmail compound call', async () => {
  if (!bridge.running) {
    console.log('SKIP: bridge not running');
    return;
  }
  const rawMessage = 'From: test@example.com\r\nTo: receiver@example.com\r\nSubject: Test\r\n\r\nHello';
  const result = await bridge.verifyEmail({
    rawMessage,
    ip: '93.184.216.34', // example.com IP
    heloDomain: 'example.com',
    hostname: 'mail.test.local',
    mailFrom: 'test@example.com',
  });
  expect(result.dkim).toBeTruthy();
  expect(result.dkim.length).toBeGreaterThan(0);
  expect(result.spf).toBeTruthy();
  // DMARC may or may not be present depending on DNS
});

tap.test('RustSecurityBridge - should stop gracefully', async () => {
  if (!bridge.running) {
    console.log('SKIP: bridge not running');
    return;
  }
  await bridge.stop();
  expect(bridge.running).toBeFalse();
});

tap.test('RustSecurityBridge - commands should fail when bridge is stopped', async () => {
  // Bridge should not be running now
  expect(bridge.running).toBeFalse();
  try {
    await bridge.ping();
    // If we get here, the bridge auto-restarted or something unexpected
    expect(true).toBeFalse(); // Should not reach here
  } catch (err) {
    expect(err).toBeTruthy(); // Expected: bridge not running error
  }
});

export default tap.start();
