// AS4 Settlement Integration Tests

import { describe, it, expect, beforeAll, afterAll } from '@jest/globals';
import { memberDirectoryService } from '@/core/settlement/as4-settlement/member-directory/member-directory.service';
import { instructionIntakeService } from '@/core/settlement/as4-settlement/instruction-intake.service';
import { as4SecurityService } from '@/core/settlement/as4/as4-security.service';

describe('AS4 Settlement Integration', () => {
  const testMemberId = 'TEST-MEMBER-001';
  const testOrganizationName = 'Test Bank';

  beforeAll(async () => {
    // Register test member
    try {
      await memberDirectoryService.registerMember({
        memberId: testMemberId,
        organizationName: testOrganizationName,
        as4EndpointUrl: 'https://test-bank.example.com/as4',
        tlsCertFingerprint: 'AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99',
        allowedMessageTypes: ['DBIS.SI.202', 'DBIS.SI.202COV'],
      });
    } catch (error) {
      // Member might already exist, ignore
    }
  });

  afterAll(async () => {
    // Cleanup test data if needed
  });

  describe('Member Directory', () => {
    it('should retrieve registered member', async () => {
      const member = await memberDirectoryService.getMember(testMemberId);
      expect(member).not.toBeNull();
      expect(member?.memberId).toBe(testMemberId);
      expect(member?.organizationName).toBe(testOrganizationName);
    });

    it('should search members by status', async () => {
      const members = await memberDirectoryService.searchMembers({ status: 'active' });
      expect(members.length).toBeGreaterThan(0);
      expect(members.some((m) => m.memberId === testMemberId)).toBe(true);
    });
  });

  describe('Security', () => {
    it('should generate replay nonce', () => {
      const nonce = as4SecurityService.generateReplayNonce();
      expect(nonce).toBeDefined();
      expect(nonce.length).toBeGreaterThan(0);
    });

    it('should calculate payload hash', () => {
      const payload = 'test payload';
      const hash = as4SecurityService.calculatePayloadHash(payload);
      expect(hash).toBeDefined();
      expect(hash.length).toBe(64); // SHA-256 hex string
    });
  });

  describe('Instruction Intake', () => {
    it('should process valid instruction', async () => {
      const as4Message = {
        MessageId: 'MSG-TEST-001',
        BusinessType: 'DBIS.SI.202',
        CreatedAt: new Date().toISOString(),
        FromMemberId: testMemberId,
        ToMemberId: 'DBIS',
        CorrelationId: 'CORR-001',
        ReplayNonce: as4SecurityService.generateReplayNonce(),
        SchemaVersion: '1.0',
        Instr: {
          InstrId: 'INSTR-TEST-001',
          ValueDate: new Date().toISOString().split('T')[0],
          Currency: 'USD',
          Amount: '1000.00',
          DebtorAccount: `MSA:${testMemberId}:USD`,
          CreditorAccount: 'MSA:TEST-MEMBER-002:USD',
        },
      };

      const payloadHash = as4SecurityService.calculatePayloadHash(JSON.stringify(as4Message));

      const result = await instructionIntakeService.processInstruction(
        as4Message,
        testMemberId,
        payloadHash
      );

      expect(result.status).toBe('ACCEPTED');
      expect(result.instructionId).toBe('INSTR-TEST-001');
    });

    it('should reject duplicate instruction', async () => {
      const as4Message = {
        MessageId: 'MSG-TEST-002',
        BusinessType: 'DBIS.SI.202',
        CreatedAt: new Date().toISOString(),
        FromMemberId: testMemberId,
        ToMemberId: 'DBIS',
        CorrelationId: 'CORR-002',
        ReplayNonce: as4SecurityService.generateReplayNonce(),
        SchemaVersion: '1.0',
        Instr: {
          InstrId: 'INSTR-TEST-DUP',
          ValueDate: new Date().toISOString().split('T')[0],
          Currency: 'USD',
          Amount: '1000.00',
          DebtorAccount: `MSA:${testMemberId}:USD`,
          CreditorAccount: 'MSA:TEST-MEMBER-002:USD',
        },
      };

      const payloadHash = as4SecurityService.calculatePayloadHash(JSON.stringify(as4Message));

      // First submission
      await instructionIntakeService.processInstruction(
        as4Message,
        testMemberId,
        payloadHash
      );

      // Duplicate submission
      const result = await instructionIntakeService.processInstruction(
        as4Message,
        testMemberId,
        payloadHash
      );

      expect(result.status).toBe('ACCEPTED'); // Should be accepted as duplicate
      expect(result.existingInstructionId).toBeDefined();
    });
  });
});
