// AS4 Message Transformer Service
// Transforms messages between AS4 format and internal format

import { v4 as uuidv4 } from 'uuid';

export interface InternalInstruction {
  instructionId: string;
  messageId: string;
  fromMemberId: string;
  toMemberId: string;
  correlationId: string;
  businessType: string;
  valueDate: Date;
  currency: string;
  amount: string;
  debtorAccount: string;
  creditorAccount: string;
  charges?: string;
  feeScheduleRef?: string;
  purposeCode?: string;
  narrative?: string;
  compliancePackageRef?: string;
  createdAt: Date;
}

export interface InternalAdvice {
  adviceId: string;
  messageId: string;
  instructionId: string;
  adviceType: string;
  postedAt: Date;
  postingId: string;
  creditedAccount?: string;
  debitedAccount?: string;
  currency: string;
  amount: string;
  balanceAfter?: string;
  finalityStatus: string;
}

export class MessageTransformerService {
  /**
   * Transform AS4 instruction message to internal format
   */
  transformInstructionToInternal(as4Message: any): InternalInstruction {
    return {
      instructionId: as4Message.Instr.InstrId,
      messageId: as4Message.MessageId,
      fromMemberId: as4Message.FromMemberId,
      toMemberId: as4Message.ToMemberId,
      correlationId: as4Message.CorrelationId || uuidv4(),
      businessType: as4Message.BusinessType,
      valueDate: new Date(as4Message.Instr.ValueDate),
      currency: as4Message.Instr.Currency,
      amount: as4Message.Instr.Amount,
      debtorAccount: as4Message.Instr.DebtorAccount,
      creditorAccount: as4Message.Instr.CreditorAccount,
      charges: as4Message.Instr.Charges,
      feeScheduleRef: as4Message.Instr.FeeScheduleRef,
      purposeCode: as4Message.Instr.PurposeCode,
      narrative: as4Message.Instr.Narrative,
      compliancePackageRef: as4Message.Instr.CompliancePackageRef,
      createdAt: new Date(as4Message.CreatedAt),
    };
  }

  /**
   * Transform internal instruction to AS4 format
   */
  transformInstructionToAs4(internal: InternalInstruction): any {
    return {
      MessageId: internal.messageId,
      BusinessType: internal.businessType,
      CreatedAt: internal.createdAt.toISOString(),
      FromMemberId: internal.fromMemberId,
      ToMemberId: internal.toMemberId,
      CorrelationId: internal.correlationId,
      SchemaVersion: '1.0',
      Instr: {
        InstrId: internal.instructionId,
        ValueDate: internal.valueDate.toISOString().split('T')[0],
        Currency: internal.currency,
        Amount: internal.amount,
        DebtorAccount: internal.debtorAccount,
        CreditorAccount: internal.creditorAccount,
        Charges: internal.charges,
        FeeScheduleRef: internal.feeScheduleRef,
        PurposeCode: internal.purposeCode,
        Narrative: internal.narrative,
        CompliancePackageRef: internal.compliancePackageRef,
      },
    };
  }

  /**
   * Transform internal advice to AS4 format (MT910)
   */
  transformAdviceToAs4(internal: InternalAdvice, fromMemberId: string = 'DBIS'): any {
    if (internal.adviceType === 'DBIS.AD.910') {
      return {
        MessageId: internal.messageId,
        BusinessType: 'DBIS.AD.910',
        CreatedAt: new Date().toISOString(),
        FromMemberId: fromMemberId,
        ToMemberId: internal.creditedAccount?.split(':')[1] || '',
        CorrelationId: internal.instructionId,
        Advice: {
          AdviceId: internal.adviceId,
          OriginalInstrId: internal.instructionId,
          PostedAt: internal.postedAt.toISOString(),
          PostingId: internal.postingId,
          CreditedAccount: internal.creditedAccount,
          Currency: internal.currency,
          Amount: internal.amount,
          BalanceAfter: internal.balanceAfter,
          FinalityStatus: internal.finalityStatus,
        },
      };
    } else if (internal.adviceType === 'DBIS.AD.900') {
      return {
        MessageId: internal.messageId,
        BusinessType: 'DBIS.AD.900',
        CreatedAt: new Date().toISOString(),
        FromMemberId: fromMemberId,
        ToMemberId: internal.debitedAccount?.split(':')[1] || '',
        CorrelationId: internal.instructionId,
        Advice: {
          AdviceId: internal.adviceId,
          OriginalInstrId: internal.instructionId,
          PostedAt: internal.postedAt.toISOString(),
          PostingId: internal.postingId,
          DebitedAccount: internal.debitedAccount,
          Currency: internal.currency,
          Amount: internal.amount,
          BalanceAfter: internal.balanceAfter,
          FinalityStatus: internal.finalityStatus,
        },
      };
    }

    throw new Error(`Unknown advice type: ${internal.adviceType}`);
  }
}

export const messageTransformerService = new MessageTransformerService();
