import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { resolve } from 'path';
import { buildResourceRegistry, loadListenerConfig } from '../src/resourceRegistry';
import { parseSwiftFin, parseIso20022, parseInbound } from '../src/parsers/inboundParser';
import { matchResources } from '../src/matchers/resourceMatcher';
import { createSwiftListener } from '../src/listener';

const ROOT = resolve(__dirname, '../../../..');

const SAMPLE_MT103 = `{1:F01BANKUS33AXXX0000000000}{2:I103BANKDEFFXXXXN}{3:{108:MT103}}{4:
:20:CHAIN138-abc123ref
:23B:CRED
:32A:230101USD1000,00
:50K:/123456
Ordering Customer
:59:/987654
Beneficiary
:70:cWUSDC settlement on chain138 via 0xf22258f57794CC8E06237084b353Ab30fFfa640b
-}`;

beforeEach(() => {
  delete process.env.PRIVATE_KEY;
  process.env.SWIFT_LISTENER_GATEWAY_EXECUTE = '0';
  vi.stubGlobal(
    'fetch',
    vi.fn(async () => new Response(JSON.stringify({ id: 'test' }), { status: 201 }))
  );
});

afterEach(() => {
  vi.unstubAllGlobals();
});

describe('swift-listener parsers', () => {
  it('parses MT103 with remittance referencing cWUSDC and chain138 address', () => {
    const parsed = parseSwiftFin(SAMPLE_MT103);
    expect(parsed.messageType).toBe('MT103');
    expect(parsed.parsed.senderReference).toBe('CHAIN138-abc123ref');
    expect(parsed.parsed.remittanceInfo).toContain('cWUSDC');
  });

  it('detects iso20022 pacs.008', () => {
    const xml = `<?xml version="1.0"?><Document xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.08">
      <FIToFICstmrCdtTrf><GrpHdr><MsgId>MSG1</MsgId></GrpHdr>
      <CdtTrfTxInf><PmtId><InstrId>CHAIN138-test</InstrId></PmtId>
      <IntrBkSttlmAmt Ccy="USD">100</IntrBkSttlmAmt>
      <RmtInf><Ustrd>Defi Oracle Meta chain 138 cUSDT pool</Ustrd></RmtInf>
      </CdtTrfTxInf></FIToFICstmrCdtTrf></Document>`;
    const parsed = parseIso20022(xml);
    expect(parsed.messageType).toBe('pacs.008');
    expect(parsed.parsed.instructionId).toBe('CHAIN138-test');
  });
});

describe('resource matcher', () => {
  it('matches Chain 138 symbols, addresses, and cW* references', () => {
    const config = loadListenerConfig(ROOT);
    const registry = buildResourceRegistry(ROOT, config);
    const parsed = parseInbound(SAMPLE_MT103);
    const matches = matchResources(registry, parsed);
    expect(matches.some((m) => m.kind === 'instruction_prefix')).toBe(true);
    expect(matches.some((m) => m.kind === 'cw_symbol' && m.value === 'cWUSDC')).toBe(true);
    expect(matches.some((m) => m.kind === 'chain138_address')).toBe(true);
  });
});

describe('listener pipeline', () => {
  it('processes matched inbound and skips duplicates', async () => {
    const listener = createSwiftListener(ROOT);
    const msg = {
      source: `test:mt103:${Date.now()}`,
      format: 'swift_fin' as const,
      payload: SAMPLE_MT103,
    };
    const first = await listener.processMessage(msg);
    expect(first?.matched).toBe(true);
    expect(first?.matches.length).toBeGreaterThan(0);
    expect(first?.canonical?.instructionId).toContain('CHAIN138');
    const second = await listener.processMessage(msg);
    expect(second).toBeNull();
  });
});
