/**
 * SBV ISO 20022 — pacs.009.001.09 mBridge Outbound Builder
 * Xây dựng message FinancialInstitutionCreditTransfer (pacs.009) cho ASEAN mBridge.
 *
 * Điểm khác biệt so với pacs.008:
 *   - Không có thông tin KH trực tiếp trong GrpHdr
 *   - Bắt buộc có UndrlygCstmrCdtTrf (dữ liệu KH gốc) cho cross-border traceability
 *   - ClrSys.Cd = 'MBRIDGE'
 *   - SttlmMtd = 'CLRG' (clearing qua mBridge)
 *
 * Tham chiếu: architecture.md §2.2 pacs.009.001, §4 UndrlygCstmrCdtTrf
 * Cơ quan chủ quản: Ngân hàng Nhà nước Việt Nam (SBV)
 */

import { Builder } from 'xml2js';
import { v4 as uuidv4 } from 'uuid';
import { createHash } from 'crypto';

// ─── Types ───────────────────────────────────────────────────────────────────

/** Dữ liệu KH gốc cần đính kèm cho cross-border traceability (FATF R.16) */
export interface UnderlyingCustomerTransfer {
  /** End-to-end ID của giao dịch KH gốc */
  endToEndId:    string;
  /** UETR của giao dịch KH gốc */
  uetr?:         string;
  /** Tên người gửi */
  debtorName:    string;
  /** Số tài khoản người gửi */
  debtorAcct:    string;
  /** BIC ngân hàng người gửi */
  debtorBic:     string;
  /** Tên người nhận */
  creditorName:  string;
  /** Số tài khoản người nhận */
  creditorAcct:  string;
  /** BIC ngân hàng người nhận */
  creditorBic:   string;
  /** Mục đích thanh toán */
  purposeCode?:  string;
  /** Nội dung chuyển tiền */
  remittanceInfo?: string;
}

/** Input cho pacs.009 mBridge */
export interface Pacs009Input {
  /** Message ID duy nhất (max 35 ký tự) */
  msgId:         string;
  /** BIC ngân hàng gửi (NHTM Việt Nam) */
  instructingBic: string;
  /** BIC ngân hàng nhận (đối tác ASEAN) */
  instructedBic:  string;
  /** Số tiền chuyển vốn liên ngân hàng */
  amount:         number;
  /** Mã tiền tệ */
  currency:       string;
  /** Ngày quyết toán (YYYY-MM-DD) */
  settlementDate: string;
  /** Dữ liệu KH gốc (bắt buộc cho cross-border) */
  underlyingCustomer: UnderlyingCustomerTransfer;
  /** Ghi chú nội bộ mBridge */
  remittanceInfo?:    string;
}

/** Kết quả build pacs.009 */
export interface Pacs009Result {
  isoXml:         string;
  businessAppHdr: string;
  messageHash:    string;
  uetr:           string;
}

// ─── Constants ───────────────────────────────────────────────────────────────

const NS_PACS009 = 'urn:iso:std:iso:20022:tech:xsd:pacs.009.001.09';
const NS_HEAD001 = 'urn:iso:std:iso:20022:tech:xsd:head.001.001.03';
const SBV_BIC    = 'SBVNVNVX';

// ─── Builder ─────────────────────────────────────────────────────────────────

/**
 * Xây dựng pacs.009.001.09 cho kết nối ASEAN mBridge.
 * Tự động gán UETR mới, timestamp UTC+7, và Business Application Header.
 */
export function buildPacs009(input: Pacs009Input): Pacs009Result {
  const uetr    = uuidv4();
  const now     = new Date();
  const creDtTm = toIsoUtc7(now);
  const txId    = `TXN-MBRIDGE-${input.msgId}`;

  const ucct = input.underlyingCustomer;

  const pacs009 = {
    Document: {
      $: { xmlns: NS_PACS009 },
      FICdtTrf: {
        GrpHdr: {
          MsgId:    input.msgId,
          CreDtTm:  creDtTm,
          NbOfTxs:  '1',
          SttlmInf: {
            SttlmMtd: 'CLRG',
            ClrSys:   { Cd: 'MBRIDGE' },
          },
          InstgAgt: { FinInstnId: { BICFI: input.instructingBic } },
          InstdAgt: { FinInstnId: { BICFI: input.instructedBic  } },
        },
        CdtTrfTxInf: [
          {
            PmtId: {
              InstrId:     input.msgId,
              EndToEndId:  input.msgId,
              UETR:        uetr,
              TxId:        txId,
            },
            IntrBkSttlmAmt: {
              _: input.amount.toFixed(2),
              $: { Ccy: input.currency },
            },
            IntrBkSttlmDt: input.settlementDate,
            ...(input.remittanceInfo ? { RmtInf: { Ustrd: input.remittanceInfo.slice(0, 140) } } : {}),
            InstgAgt: { FinInstnId: { BICFI: input.instructingBic } },
            InstdAgt: { FinInstnId: { BICFI: input.instructedBic  } },

            // UndrlygCstmrCdtTrf — trường bắt buộc cho xuyên biên giới (FATF R.16)
            UndrlygCstmrCdtTrf: {
              PmtId: {
                EndToEndId: ucct.endToEndId,
                ...(ucct.uetr ? { UETR: ucct.uetr } : {}),
              },
              Amt: {
                InstdAmt: {
                  _: input.amount.toFixed(2),
                  $: { Ccy: input.currency },
                },
              },
              ...(ucct.purposeCode   ? { Purp:   { Cd:    ucct.purposeCode } } : {}),
              ...(ucct.remittanceInfo ? { RmtInf: { Ustrd: ucct.remittanceInfo.slice(0, 140) } } : {}),
              Dbtr:     { Nm: ucct.debtorName.slice(0, 140) },
              DbtrAcct: { Id: { Othr: { Id: ucct.debtorAcct } } },
              DbtrAgt:  { FinInstnId: { BICFI: ucct.debtorBic } },
              Cdtr:     { Nm: ucct.creditorName.slice(0, 140) },
              CdtrAcct: { Id: { Othr: { Id: ucct.creditorAcct } } },
              CdtrAgt:  { FinInstnId: { BICFI: ucct.creditorBic } },
            },
          }
        ],
      },
    }
  };

  const builder   = new Builder({ xmldec: { version: '1.0', encoding: 'UTF-8' } });
  const isoXml    = builder.buildObject(pacs009);
  const msgHash   = createHash('sha256').update(isoXml, 'utf8').digest('hex');
  const appHdr    = buildHead001(input.msgId, creDtTm, NS_PACS009, input.instructingBic);

  return { isoXml, businessAppHdr: appHdr, messageHash: msgHash, uetr };
}

// ─── Helpers ─────────────────────────────────────────────────────────────────

function toIsoUtc7(d: Date): string {
  const offset = 7 * 60 * 60 * 1000;
  const local  = new Date(d.getTime() + offset);
  return local.toISOString().replace('Z', '+07:00');
}

function buildHead001(msgId: string, creDt: string, msgDefId: string, fromBic: string): string {
  const header = {
    AppHdr: {
      $:         { xmlns: NS_HEAD001 },
      Fr:        { FIId: { FinInstnId: { BICFI: fromBic } } },
      To:        { FIId: { FinInstnId: { BICFI: SBV_BIC } } },
      BizMsgIdr: msgId,
      MsgDefIdr: msgDefId,
      CreDt:     creDt,
    }
  };
  return new Builder({ xmldec: { version: '1.0', encoding: 'UTF-8' } }).buildObject(header);
}
