// AS4 Gateway Service
// Orchestrates AS4 message processing, routing, and integration

import { as4MshService } from './as4-msh.service';
import { as4SecurityService } from './as4-security.service';
import { memberDirectoryService } from '../as4-settlement/member-directory/member-directory.service';
import { logger } from '@/infrastructure/monitoring/logger';

export interface GatewayMessage {
  messageId: string;
  fromMemberId: string;
  toMemberId: string;
  businessType: string;
  payload: string;
  tlsCertFingerprint: string;
  properties?: Record<string, string>;
}

export interface GatewayResult {
  messageId: string;
  status: 'ACCEPTED' | 'REJECTED';
  receipt?: any;
  error?: string;
  routingDecision?: {
    routeTo: string;
    reason: string;
  };
}

export class As4GatewayService {
  /**
   * Process incoming message at gateway
   */
  async processIncomingMessage(message: GatewayMessage): Promise<GatewayResult> {
    try {
      // Step 1: Validate member
      const member = await memberDirectoryService.getMember(message.fromMemberId);
      if (!member || member.status !== 'active') {
        return {
          messageId: message.messageId,
          status: 'REJECTED',
          error: 'Member not found or inactive',
        };
      }

      // Step 2: Validate message type is allowed
      if (!member.allowedMessageTypes.includes(message.businessType)) {
        return {
          messageId: message.messageId,
          status: 'REJECTED',
          error: `Message type ${message.businessType} not allowed for member ${message.fromMemberId}`,
        };
      }

      // Step 3: Create AS4 user message
      const as4Message = as4MshService.createUserMessage({
        conversationId: `CONV-${message.messageId}`,
        service: 'DBIS.Settlement',
        action: message.businessType,
        fromPartyId: message.fromMemberId,
        toPartyId: message.toMemberId,
        payload: message.payload,
        properties: {
          ...message.properties,
          replayNonce: as4SecurityService.generateReplayNonce(),
        },
      });

      // Step 4: Process through MSH
      const result = await as4MshService.processIncomingMessage(
        as4Message,
        message.fromMemberId,
        message.tlsCertFingerprint
      );

      // Step 5: Determine routing
      const routingDecision = await this.determineRouting(message);

      return {
        ...result,
        routingDecision,
      };
    } catch (error) {
      logger.error('Gateway message processing failed', {
        messageId: message.messageId,
        error: error instanceof Error ? error.message : 'Unknown error',
      });

      return {
        messageId: message.messageId,
        status: 'REJECTED',
        error: error instanceof Error ? error.message : 'Unknown error',
      };
    }
  }

  /**
   * Determine message routing
   */
  private async determineRouting(message: GatewayMessage): Promise<{
    routeTo: string;
    reason: string;
  }> {
    // If toMemberId is DBIS, route to settlement core
    if (message.toMemberId === 'DBIS') {
      return {
        routeTo: 'settlement-core',
        reason: 'DBIS settlement instruction',
      };
    }

    // Otherwise, route to member's AS4 endpoint
    const recipient = await memberDirectoryService.getMember(message.toMemberId);
    if (recipient) {
      return {
        routeTo: recipient.as4EndpointUrl,
        reason: 'Member-to-member routing',
      };
    }

    return {
      routeTo: 'unknown',
      reason: 'Recipient not found',
    };
  }

  /**
   * Route message to settlement core
   */
  async routeToSettlementCore(messageId: string, payload: string): Promise<void> {
    // TODO: Publish to integration bus (Kafka/RabbitMQ)
    // For now, log
    logger.info('Message routed to settlement core', { messageId });
  }

  /**
   * Route message to member endpoint
   */
  async routeToMember(memberId: string, message: any): Promise<void> {
    const member = await memberDirectoryService.getMember(memberId);
    if (!member) {
      throw new Error(`Member ${memberId} not found`);
    }

    // Send via AS4 MSH
    await as4MshService.sendOutgoingMessage(
      {
        messageId: message.messageId,
        conversationId: message.conversationId,
        service: message.service,
        action: message.action,
        fromPartyId: 'DBIS',
        toPartyId: memberId,
        payload: message.payload,
        timestamp: new Date(),
      },
      memberId
    );
  }
}

export const as4GatewayService = new As4GatewayService();
