/**
 * SBV ISO 20022 API Gateway — Entry Point
 * Ngân hàng Nhà nước Việt Nam
 */

import express from 'express';
import helmet from 'helmet';
import morgan from 'morgan';
import { router } from './gateway/iso20022-router';
import { vnlhRouter } from './gateway/vnlh-router';
import { disconnectKafka } from './gateway/kafka-publisher';

const app  = express();
const PORT = parseInt(process.env.PORT ?? '8080', 10);
const HOST = process.env.HOST ?? '127.0.0.1';

// ─── Middleware ───────────────────────────────────────────────────────────────
app.use(helmet());
app.use(morgan('[:date[iso]] :method :url :status :response-time ms'));
app.use(express.json({ limit: '2mb' }));
app.use(express.text({ type: ['application/xml', 'text/xml'], limit: '2mb' }));

// ─── Routes ───────────────────────────────────────────────────────────────────
app.use('/api/v1/iso20022', router);
app.use('/api/v1/iso20022/vnlh', vnlhRouter);

app.get('/', (_req, res) => {
  res.json({ service: 'SBV ISO 20022 API Gateway', version: '1.0.0', status: 'running', docs: '/api/v1/iso20022/health' });
});

app.use((_req, res) => {
  res.status(404).json({ code: 'NOT_FOUND', message: 'Endpoint không tồn tại' });
});

// ─── Start ────────────────────────────────────────────────────────────────────
const server = app.listen(PORT, HOST, () => {
  console.log(`\n  SBV ISO 20022 Gateway  v1.0.0`);
  console.log(`  ──────────────────────────────`);
  console.log(`  Listening : http://${HOST}:${PORT}`);
  console.log(`  Health    : http://${HOST}:${PORT}/api/v1/iso20022/health`);
  console.log(`  Inbound   : POST http://${HOST}:${PORT}/api/v1/iso20022/inbound`);
  console.log(`  Pain001   : POST http://${HOST}:${PORT}/api/v1/iso20022/outbound/pain001`);
  console.log(`  mBridge   : POST http://${HOST}:${PORT}/api/v1/iso20022/outbound/pacs009`);
  console.log(`  AML/CFT   : POST http://${HOST}:${PORT}/api/v1/iso20022/auth/aml-report`);
  console.log(`  Migrate   : POST http://${HOST}:${PORT}/api/v1/iso20022/ibps-migrate`);
  console.log(`  Status    : GET  http://${HOST}:${PORT}/api/v1/iso20022/status/:uetr`);
  console.log(`  ──────────── VNLH-VND SDK ─────────────────────────`);
  console.log(`  AML Screen: POST http://${HOST}:${PORT}/api/v1/iso20022/vnlh/screen`);
  console.log(`  Netting   : POST http://${HOST}:${PORT}/api/v1/iso20022/vnlh/netting`);
  console.log(`  FX-Check  : POST http://${HOST}:${PORT}/api/v1/iso20022/vnlh/fx-check`);
  console.log(`  Chain     : GET  http://${HOST}:${PORT}/api/v1/iso20022/vnlh/chain/:hash`);
  console.log(`  Policies  : GET  http://${HOST}:${PORT}/api/v1/iso20022/vnlh/policies`);
  console.log(`  SDK Info  : GET  http://${HOST}:${PORT}/api/v1/iso20022/vnlh/sdk-info`);
  console.log(`  ──────────── KYC / eKYC / ODC SDK ─────────────────────────`);
  console.log(`  KYC Submit: POST http://${HOST}:${PORT}/api/v1/iso20022/vnlh/kyc/submit`);
  console.log(`  ODC Scan  : POST http://${HOST}:${PORT}/api/v1/iso20022/vnlh/kyc/scan`);
  console.log(`  Contract  : POST http://${HOST}:${PORT}/api/v1/iso20022/vnlh/kyc/contract`);
  console.log(`  KYC Schema: GET  http://${HOST}:${PORT}/api/v1/iso20022/vnlh/kyc/schemas\n`);
});

// EADDRINUSE — thay vì crash không rõ lý do, in hướng dẫn fix
server.on('error', (err: NodeJS.ErrnoException) => {
  if (err.code === 'EADDRINUSE') {
    console.error(`\n[SBV-GW] ✗  Port ${PORT} đang bị chiếm.`);
    console.error(`[SBV-GW]    Chạy lệnh sau để giải phóng:\n`);
    console.error(`             lsof -ti TCP:${PORT} | xargs kill -9\n`);
    console.error(`             hoặc:  ./run.sh stop\n`);
  } else {
    console.error('[SBV-GW] Server error:', err.message);
  }
  process.exit(1);
});

// ─── Graceful shutdown ────────────────────────────────────────────────────────
const shutdown = (signal: string) => {
  console.log(`\n[SBV-GW] ${signal} — shutting down gracefully...`);
  server.close(async () => {
    await disconnectKafka().catch(() => undefined);
    console.log('[SBV-GW] Server closed.');
    process.exit(0);
  });
  setTimeout(() => process.exit(1), 5000);
};

process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('SIGINT',  () => shutdown('SIGINT'));

export default app;
