// AS4 Message Service Handler (MSH)
// ebMS3/AS4 compliant message handler

import { v4 as uuidv4 } from 'uuid';
import { as4SecurityService } from './as4-security.service';
import { as4ReceiptService } from './as4-receipt.service';
import { as4PayloadVaultService } from './as4-payload-vault.service';
import { memberDirectoryService } from '../as4-settlement/member-directory/member-directory.service';
import { logger } from '@/infrastructure/monitoring/logger';

export interface As4UserMessage {
  messageId: string;
  conversationId: string;
  service: string;
  action: string;
  fromPartyId: string;
  toPartyId: string;
  payload: string;
  properties?: Record<string, string>;
  timestamp: Date;
}

export interface As4MessageResult {
  messageId: string;
  receipt?: {
    receiptId: string;
    receiptType: 'NRO' | 'NRR';
    signature: any;
  };
  status: 'ACCEPTED' | 'REJECTED';
  error?: string;
}

export class As4MshService {
  /**
   * Process incoming AS4 message
   */
  async processIncomingMessage(
    message: As4UserMessage,
    memberId: string,
    tlsCertFingerprint: string
  ): Promise<As4MessageResult> {
    // Validate TLS certificate
    const tlsValid = await as4SecurityService.validateTlsCertificate(memberId, tlsCertFingerprint);
    if (!tlsValid) {
      logger.warn('TLS certificate validation failed', { memberId, tlsCertFingerprint });
      return {
        messageId: message.messageId,
        status: 'REJECTED',
        error: 'TLS certificate validation failed',
      };
    }

    // Validate member
    const member = await memberDirectoryService.getMember(memberId);
    if (!member || member.status !== 'active') {
      logger.warn('Member not found or inactive', { memberId });
      return {
        messageId: message.messageId,
        status: 'REJECTED',
        error: 'Member not found or inactive',
      };
    }

    // Validate replay nonce (if present in properties)
    if (message.properties?.replayNonce) {
      const nonceValid = await as4SecurityService.validateReplayNonce(
        memberId,
        message.properties.replayNonce
      );
      if (!nonceValid) {
        logger.warn('Replay nonce validation failed', { memberId, messageId: message.messageId });
        return {
          messageId: message.messageId,
          status: 'REJECTED',
          error: 'Replay nonce validation failed',
        };
      }
    }

    // Store payload in vault
    await as4PayloadVaultService.storePayload({
      messageId: message.messageId,
      payload: message.payload,
      payloadType: 'INSTRUCTION',
      memberId,
    });

    // Generate receipt (NRR)
    const receipt = await as4ReceiptService.generateReceipt(message.messageId, memberId, 'NRR');

    logger.info('AS4 message processed', {
      messageId: message.messageId,
      memberId,
      status: 'ACCEPTED',
    });

    return {
      messageId: message.messageId,
      receipt: {
        receiptId: receipt.receiptId,
        receiptType: receipt.receiptType,
        signature: receipt.signature,
      },
      status: 'ACCEPTED',
    };
  }

  /**
   * Send outgoing AS4 message
   */
  async sendOutgoingMessage(
    message: As4UserMessage,
    recipientMemberId: string
  ): Promise<As4MessageResult> {
    // Validate recipient
    const recipient = await memberDirectoryService.getMember(recipientMemberId);
    if (!recipient || recipient.status !== 'active') {
      logger.warn('Recipient not found or inactive', { recipientMemberId });
      return {
        messageId: message.messageId,
        status: 'REJECTED',
        error: 'Recipient not found or inactive',
      };
    }

    // TODO: Actually send message to recipient's AS4 endpoint
    // This would use HTTP POST to recipient.as4EndpointUrl
    // For now, log and return success

    logger.info('AS4 message sent', {
      messageId: message.messageId,
      recipientMemberId,
      endpoint: recipient.as4EndpointUrl,
    });

    return {
      messageId: message.messageId,
      status: 'ACCEPTED',
    };
  }

  /**
   * Create AS4 user message
   */
  createUserMessage(data: {
    conversationId: string;
    service: string;
    action: string;
    fromPartyId: string;
    toPartyId: string;
    payload: string;
    properties?: Record<string, string>;
  }): As4UserMessage {
    return {
      messageId: `MSG-${uuidv4()}`,
      conversationId: data.conversationId,
      service: data.service,
      action: data.action,
      fromPartyId: data.fromPartyId,
      toPartyId: data.toPartyId,
      payload: data.payload,
      properties: data.properties,
      timestamp: new Date(),
    };
  }
}

export const as4MshService = new As4MshService();
