// AS4 Advice Generator Service
// Creates MT900/MT910 equivalents

import { v4 as uuidv4 } from 'uuid';
import prisma from '@/shared/database/prisma';
import { Decimal } from '@prisma/client/runtime/library';
import { messageTransformerService, InternalAdvice } from './messages/message-transformer.service';
import { as4MshService } from '../as4/as4-msh.service';
import { logger } from '@/infrastructure/monitoring/logger';

export class AdviceGeneratorService {
  /**
   * Generate and send credit advice (MT910)
   */
  async generateCreditAdvice(data: {
    instructionId: string;
    postingId: string;
    creditorAccount: string;
    amount: string;
    currency: string;
    balanceAfter?: string;
  }): Promise<InternalAdvice> {
    const adviceId = `ADVICE-${uuidv4()}`;
    const messageId = `MSG-${uuidv4()}`;

    // Extract member ID from account
    const creditorMemberId = data.creditorAccount.split(':')[1];

    const advice: InternalAdvice = {
      adviceId,
      messageId,
      instructionId: data.instructionId,
      adviceType: 'DBIS.AD.910',
      postedAt: new Date(),
      postingId: data.postingId,
      creditedAccount: data.creditorAccount,
      currency: data.currency,
      amount: data.amount,
      balanceAfter: data.balanceAfter,
      finalityStatus: 'FINAL',
    };

    // Store advice in database
    await prisma.as4Advice.create({
      data: {
        id: uuidv4(),
        adviceId,
        instructionId: data.instructionId,
        adviceType: advice.adviceType,
        postedAt: advice.postedAt,
        postingId: advice.postingId,
        creditedAccount: advice.creditedAccount,
        currency: advice.currency,
        amount: new Decimal(advice.amount),
        balanceAfter: advice.balanceAfter ? new Decimal(advice.balanceAfter) : null,
        finalityStatus: advice.finalityStatus,
      },
    });

    // Transform to AS4 format and send
    const as4Message = messageTransformerService.transformAdviceToAs4(advice);
    const as4UserMessage = as4MshService.createUserMessage({
      conversationId: `CONV-${data.instructionId}`,
      service: 'DBIS.Settlement',
      action: 'DBIS.AD.910',
      fromPartyId: 'DBIS',
      toPartyId: creditorMemberId,
      payload: JSON.stringify(as4Message),
    });

    await as4MshService.sendOutgoingMessage(as4UserMessage, creditorMemberId);

    logger.info('Credit advice generated and sent', {
      adviceId,
      instructionId: data.instructionId,
      creditorMemberId,
    });

    return advice;
  }

  /**
   * Generate and send debit advice (MT900)
   */
  async generateDebitAdvice(data: {
    instructionId: string;
    postingId: string;
    debtorAccount: string;
    amount: string;
    currency: string;
    balanceAfter?: string;
  }): Promise<InternalAdvice> {
    const adviceId = `ADVICE-${uuidv4()}`;
    const messageId = `MSG-${uuidv4()}`;

    // Extract member ID from account
    const debtorMemberId = data.debtorAccount.split(':')[1];

    const advice: InternalAdvice = {
      adviceId,
      messageId,
      instructionId: data.instructionId,
      adviceType: 'DBIS.AD.900',
      postedAt: new Date(),
      postingId: data.postingId,
      debitedAccount: data.debtorAccount,
      currency: data.currency,
      amount: data.amount,
      balanceAfter: data.balanceAfter,
      finalityStatus: 'FINAL',
    };

    // Store advice in database
    await prisma.as4Advice.create({
      data: {
        id: uuidv4(),
        adviceId,
        instructionId: data.instructionId,
        adviceType: advice.adviceType,
        postedAt: advice.postedAt,
        postingId: advice.postingId,
        debitedAccount: advice.debitedAccount,
        currency: advice.currency,
        amount: new Decimal(advice.amount),
        balanceAfter: advice.balanceAfter ? new Decimal(advice.balanceAfter) : null,
        finalityStatus: advice.finalityStatus,
      },
    });

    // Transform to AS4 format and send
    const as4Message = messageTransformerService.transformAdviceToAs4(advice);
    const as4UserMessage = as4MshService.createUserMessage({
      conversationId: `CONV-${data.instructionId}`,
      service: 'DBIS.Settlement',
      action: 'DBIS.AD.900',
      fromPartyId: 'DBIS',
      toPartyId: debtorMemberId,
      payload: JSON.stringify(as4Message),
    });

    await as4MshService.sendOutgoingMessage(as4UserMessage, debtorMemberId);

    logger.info('Debit advice generated and sent', {
      adviceId,
      instructionId: data.instructionId,
      debtorMemberId,
    });

    return advice;
  }
}

export const adviceGeneratorService = new AdviceGeneratorService();
