import { createHash, randomUUID } from 'crypto';
import { mkdirSync, writeFileSync } from 'fs';
import { join, resolve } from 'path';
import {
  canonicalToPacs008Xml,
  mapPaymentLeafToCanonical,
  type CanonicalPaymentMessage,
} from '@dbis/checkpoint-core';
import type { PaymentLeaf } from './ingress/types';

function storeDir(): string {
  const raw = process.env.OMNL_ISO20022_STORE_DIR?.trim();
  if (raw) return resolve(raw);
  const root = process.env.PROXMOX_ROOT || process.cwd();
  return resolve(root, 'config/iso20022-omnl/messages');
}

function retentionUntil(fromIso: string): string {
  const y = parseInt(process.env.OMNL_ISO20022_RETENTION_YEARS || '10', 10);
  const d = new Date(fromIso);
  d.setFullYear(d.getFullYear() + (Number.isFinite(y) && y > 0 ? y : 10));
  return d.toISOString();
}

export function persistIso20022ForLeaves(
  leaves: PaymentLeaf[],
  batchId: bigint
): Array<{ id: string; chain138TxHash: string; instructionId: string }> {
  if (process.env.CHECKPOINT_ISO_OMNL_STORE === '0') return [];
  const dir = storeDir();
  mkdirSync(dir, { recursive: true });
  const out: Array<{ id: string; chain138TxHash: string; instructionId: string }> = [];
  for (const leaf of leaves) {
    const iso = leaf.iso20022 ?? mapPaymentLeafToCanonical(leaf);
    const xml = canonicalToPacs008Xml(iso);
    const id = randomUUID();
    const receivedAt = new Date().toISOString();
    const record = {
      id,
      messageType: 'pacs.008' as const,
      receivedAt,
      retentionUntil: retentionUntil(receivedAt),
      uetr: iso.uetr,
      instructionId: iso.instructionId,
      settlementOrChainRef: leaf.txHash,
      accountingRef: `checkpoint-batch-${batchId.toString()}`,
      payloadSha256: createHash('sha256').update(xml, 'utf8').digest('hex'),
      payload: xml,
      canonical: iso,
    };
    writeFileSync(join(dir, `${id}.json`), JSON.stringify(record, null, 2), 'utf8');
    out.push({ id, chain138TxHash: leaf.txHash, instructionId: iso.instructionId });
  }
  return out;
}
