/**
 * Compliance Service Tests
 */

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { ComplianceService, getComplianceService } from './compliance';
import fetch from 'node-fetch';

vi.mock('node-fetch');

describe('ComplianceService', () => {
  let service: ComplianceService;
  const subjectDid = 'did:web:example.com:subject-1';
  const subjectData = {
    name: 'Test User',
    email: 'test@example.com',
    phone: '+1234567890',
    address: '123 Test St',
    dateOfBirth: '1990-01-01',
    nationality: 'US',
  };

  beforeEach(() => {
    service = new ComplianceService();
    vi.clearAllMocks();
  });

  describe('performComplianceChecks', () => {
    it('should perform all compliance checks', async () => {
      // Mock KYC check
      (fetch as any).mockResolvedValueOnce({
        ok: true,
        json: async () => ({ verified: true }),
      });

      // Mock AML check
      (fetch as any).mockResolvedValueOnce({
        ok: true,
        json: async () => ({ cleared: true }),
      });

      // Mock Sanctions check
      (fetch as any).mockResolvedValueOnce({
        ok: true,
        json: async () => ({ match: false }),
      });

      const result = await service.performComplianceChecks(subjectDid, subjectData);

      expect(result.passed).toBe(true);
      expect(result.checks).toHaveLength(4); // KYC, AML, Sanctions, Identity
      expect(result.riskScore).toBeLessThan(70);
    });

    it('should fail on sanctions match', async () => {
      // Mock KYC check
      (fetch as any).mockResolvedValueOnce({
        ok: true,
        json: async () => ({ verified: true }),
      });

      // Mock AML check
      (fetch as any).mockResolvedValueOnce({
        ok: true,
        json: async () => ({ cleared: true }),
      });

      // Mock Sanctions check - MATCH
      (fetch as any).mockResolvedValueOnce({
        ok: true,
        json: async () => ({ match: true, matches: [{ name: 'Test User' }] }),
      });

      const result = await service.performComplianceChecks(subjectDid, subjectData);

      expect(result.passed).toBe(false);
      expect(result.riskScore).toBeGreaterThanOrEqual(70);
      expect(result.checks.some((c) => c.name === 'Sanctions Check' && !c.passed)).toBe(
        true
      );
    });

    it('should fail on high risk score', async () => {
      // Mock all checks to fail
      (fetch as any)
        .mockResolvedValueOnce({
          ok: true,
          json: async () => ({ verified: false }),
        })
        .mockResolvedValueOnce({
          ok: true,
          json: async () => ({ cleared: false, riskLevel: 'high' }),
        })
        .mockResolvedValueOnce({
          ok: true,
          json: async () => ({ match: false }),
        });

      const result = await service.performComplianceChecks(subjectDid, subjectData);

      expect(result.passed).toBe(false);
      expect(result.riskScore).toBeGreaterThanOrEqual(70);
    });

    it('should use fallback when providers not configured', async () => {
      const serviceWithoutProviders = new ComplianceService({
        enableKYC: true,
        enableAML: false,
        enableSanctions: false,
        enableIdentityVerification: true,
        kycProvider: undefined, // No provider configured
      });

      const result = await serviceWithoutProviders.performComplianceChecks(
        subjectDid,
        subjectData
      );

      // Should use fallback validation for KYC and identity verification
      expect(result.checks.length).toBeGreaterThanOrEqual(2);
      // KYC should pass with fallback (has required fields)
      expect(result.checks.find((c) => c.name === 'KYC Check')?.passed).toBe(true);
    });
  });

  describe('getComplianceService', () => {
    it('should return singleton instance', () => {
      const service1 = getComplianceService();
      const service2 = getComplianceService();

      expect(service1).toBe(service2);
    });
  });
});

