// ISO 20022 Message Handlers

import { parseString } from 'xml2js';
import { promisify } from 'util';
import {
  IsoMessage,
  IsoMessageType,
  Pacs008Message,
  Fxmt001Message,
  DbisExtension,
} from '@/shared/types';
import prisma from '@/shared/database/prisma';
import { v4 as uuidv4 } from 'uuid';

const parseXML = promisify(parseString);

export class Iso20022Service {
  /**
   * Parse ISO 20022 message
   */
  async parseMessage(rawMessage: string): Promise<IsoMessage> {
    const parsed = await parseXML(rawMessage);
    const messageType = this.detectMessageType(parsed);
    const messageId = this.extractMessageId(parsed, messageType);

    const message = await prisma.isoMessage.create({
      data: {
        messageId,
        sovereignBankId: 'UNKNOWN', // Will be set from context
        messageType,
        direction: 'inbound',
        status: 'pending',
        rawMessage,
        parsedData: parsed,
      },
    });

    return this.mapToIsoMessage(message);
  }

  /**
   * Generate PACS.008 message
   */
  async generatePacs008(message: Pacs008Message, dbisExtensions?: DbisExtension): Promise<string> {
    const xml = `<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.10">
  <FIToFICstmrCdtTrf>
    <GrpHdr>
      <MsgId>${message.messageId}</MsgId>
      <CreDtTm>${message.creationDateTime.toISOString()}</CreDtTm>
      <NbOfTxs>${message.numberOfTransactions}</NbOfTxs>
    </GrpHdr>
    <CdtTrfTxInf>
      <PmtId>
        <InstrId>${message.creditTransferTransactionInfo.paymentId.instructionId}</InstrId>
        <EndToEndId>${message.creditTransferTransactionInfo.paymentId.endToEndId}</EndToEndId>
      </PmtId>
      <IntrBkSttlmAmt Ccy="${message.creditTransferTransactionInfo.interbankSettlementAmount.currency}">
        ${message.creditTransferTransactionInfo.interbankSettlementAmount.amount}
      </IntrBkSttlmAmt>
      <Dbtr>
        <FinInstnId>
          <BICFI>${message.creditTransferTransactionInfo.debtor.financialInstitution.bicfi}</BICFI>
        </FinInstnId>
      </Dbtr>
      <Cdtr>
        <FinInstnId>
          <BICFI>${message.creditTransferTransactionInfo.creditor.financialInstitution.bicfi}</BICFI>
        </FinInstnId>
      </Cdtr>
      ${dbisExtensions ? this.generateDbisExtensions(dbisExtensions) : ''}
    </CdtTrfTxInf>
  </FIToFICstmrCdtTrf>
</Document>`;

    return xml;
  }

  /**
   * Generate DBIS extensions XML
   */
  private generateDbisExtensions(extensions: DbisExtension): string {
    return `
      <SplmtryData>
        <PlcAndNm>DBIS_EXTENSION</PlcAndNm>
        <Envlp>
          ${extensions.sovId ? `<SOV-ID>${extensions.sovId}</SOV-ID>` : ''}
          ${extensions.maci ? `<MACI>${extensions.maci}</MACI>` : ''}
          ${extensions.cbdcMode !== undefined ? `<CBDCMode>${extensions.cbdcMode}</CBDCMode>` : ''}
        </Envlp>
      </SplmtryData>`;
  }

  /**
   * Detect message type from parsed XML
   */
  private detectMessageType(parsed: any): IsoMessageType {
    if (parsed.FIToFICstmrCdtTrf) return IsoMessageType.PACS_008;
    if (parsed.BkToCstmrStmt) return IsoMessageType.CAMT_053;
    if (parsed.CstmrCdtTrfInitn) return IsoMessageType.PAIN_001;
    if (parsed.FXTradInstr) return IsoMessageType.FXMT_001;
    return IsoMessageType.PACS_008; // Default
  }

  /**
   * Extract message ID
   */
  private extractMessageId(parsed: any, messageType: IsoMessageType): string {
    // Simplified extraction
    return `MSG-${uuidv4()}`;
  }

  /**
   * Map Prisma model to IsoMessage type
   */
  private mapToIsoMessage(message: any): IsoMessage {
    return {
      id: message.id,
      messageId: message.messageId,
      sovereignBankId: message.sovereignBankId,
      messageType: message.messageType as IsoMessageType,
      direction: message.direction as 'inbound' | 'outbound',
      status: message.status as 'pending' | 'processed' | 'failed' | 'acknowledged',
      rawMessage: message.rawMessage,
      parsedData: message.parsedData as Record<string, unknown> | undefined,
      dbisExtensions: message.dbisExtensions as DbisExtension | undefined,
      hsmSignature: message.hsmSignature || undefined,
      createdAt: message.createdAt,
    };
  }
}

export const iso20022Service = new Iso20022Service();

