/**
 * @swagger
 * tags:
 *   name: Nostro/Vostro
 *   description: DBIS Nostro/Vostro Network API - Standardized integration layer for Central Banks and Financial Institutions
 */

import { Router } from 'express';
import { zeroTrustAuthMiddleware } from '@/integration/api-gateway/middleware/auth.middleware';
import { nostroVostroService } from './nostro-vostro.service';
import { reconciliationService } from './reconciliation.service';
import { webhookService } from './webhook.service';
import gruFxRoutes from './gru-fx/gru-fx.routes';

const router = Router();

// Mount GRU/FX routes
router.use('/gru-fx', gruFxRoutes);

// ============================================================================
// Participant Endpoints
// ============================================================================

/**
 * @swagger
 * /api/v1/nostro-vostro/participants:
 *   get:
 *     summary: List participants
 *     description: Retrieve a paginated list of participants (SCBs, FIs)
 *     tags: [Nostro/Vostro]
 *     security:
 *       - SovereignToken: []
 *     parameters:
 *       - in: query
 *         name: regulatoryTier
 *         schema:
 *           type: string
 *           enum: [SCB, Tier1, Tier2, PSP]
 *         description: Filter by regulatory tier
 *       - in: query
 *         name: country
 *         schema:
 *           type: string
 *         description: Filter by country (ISO 3166-1 alpha-2)
 *       - in: query
 *         name: status
 *         schema:
 *           type: string
 *           enum: [active, suspended, inactive]
 *         description: Filter by status
 *       - in: query
 *         name: page
 *         schema:
 *           type: integer
 *           default: 1
 *         description: Page number
 *       - in: query
 *         name: pageSize
 *         schema:
 *           type: integer
 *           default: 50
 *         description: Items per page
 *     responses:
 *       200:
 *         description: List of participants
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                 data:
 *                   type: object
 *                   properties:
 *                     data:
 *                       type: array
 *                       items:
 *                         $ref: '#/components/schemas/Participant'
 *                     pagination:
 *                       $ref: '#/components/schemas/Pagination'
 *       401:
 *         $ref: '#/components/responses/Unauthorized'
 *       500:
 *         $ref: '#/components/responses/InternalServerError'
 */
router.get('/participants', zeroTrustAuthMiddleware, async (req, res, next) => {
  try {
    const result = await nostroVostroService.listParticipants({
      regulatoryTier: req.query.regulatoryTier as string,
      country: req.query.country as string,
      status: req.query.status as string,
      page: req.query.page ? parseInt(req.query.page as string) : undefined,
      pageSize: req.query.pageSize ? parseInt(req.query.pageSize as string) : undefined,
    });

    res.json({
      success: true,
      data: result,
      timestamp: new Date(),
    });
  } catch (error) {
      return next(error);
  }
});

/**
 * @swagger
 * /api/v1/nostro-vostro/participants/{participantId}:
 *   get:
 *     summary: Get participant details
 *     description: Retrieve details for a specific participant
 *     tags: [Nostro/Vostro]
 *     security:
 *       - SovereignToken: []
 *     parameters:
 *       - in: path
 *         name: participantId
 *         required: true
 *         schema:
 *           type: string
 *         description: Participant ID
 *     responses:
 *       200:
 *         description: Participant details
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                 data:
 *                   $ref: '#/components/schemas/Participant'
 *       404:
 *         $ref: '#/components/responses/NotFound'
 *       401:
 *         $ref: '#/components/responses/Unauthorized'
 */
router.get('/participants/:participantId', zeroTrustAuthMiddleware, async (req, res, next) => {
  try {
    const participant = await nostroVostroService.getParticipant(req.params.participantId);

    if (!participant) {
      return res.status(404).json({
        success: false,
        error: { code: 'NOT_FOUND', message: 'Participant not found' },
        timestamp: new Date(),
      });
    }

    res.json({
      success: true,
      data: participant,
      timestamp: new Date(),
    });
  } catch (error) {
      return next(error);
  }
});

/**
 * @swagger
 * /api/v1/nostro-vostro/participants:
 *   post:
 *     summary: Create participant
 *     description: Register a new participant (SCB or FI)
 *     tags: [Nostro/Vostro]
 *     security:
 *       - SovereignToken: []
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             $ref: '#/components/schemas/ParticipantCreateRequest'
 *           example:
 *             name: "Central Bank of Example"
 *             bic: "CBEXUS33"
 *             lei: "5493000X9ZXSQ9B6Y815"
 *             country: "US"
 *             regulatoryTier: "SCB"
 *     responses:
 *       201:
 *         description: Participant created successfully
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                 data:
 *                   $ref: '#/components/schemas/Participant'
 *       400:
 *         $ref: '#/components/responses/BadRequest'
 *       401:
 *         $ref: '#/components/responses/Unauthorized'
 */
router.post('/participants', zeroTrustAuthMiddleware, async (req, res, next) => {
  try {
    const participant = await nostroVostroService.createParticipant(req.body);

    res.status(201).json({
      success: true,
      data: participant,
      timestamp: new Date(),
    });
  } catch (error) {
      return next(error);
  }
});

// ============================================================================
// Account Endpoints
// ============================================================================

/**
 * @swagger
 * /api/v1/nostro-vostro/accounts:
 *   get:
 *     summary: List Nostro/Vostro accounts
 *     description: Retrieve a paginated list of accounts
 *     tags: [Nostro/Vostro]
 *     security:
 *       - SovereignToken: []
 *     parameters:
 *       - in: query
 *         name: ownerParticipantId
 *         schema:
 *           type: string
 *         description: Filter by owner participant ID
 *       - in: query
 *         name: counterpartyParticipantId
 *         schema:
 *           type: string
 *         description: Filter by counterparty participant ID
 *       - in: query
 *         name: accountType
 *         schema:
 *           type: string
 *           enum: [NOSTRO, VOSTRO]
 *         description: Filter by account type
 *       - in: query
 *         name: currency
 *         schema:
 *           type: string
 *         description: Filter by currency (ISO 4217)
 *       - in: query
 *         name: status
 *         schema:
 *           type: string
 *           enum: [ACTIVE, SUSPENDED, CLOSED]
 *       - in: query
 *         name: page
 *         schema:
 *           type: integer
 *           default: 1
 *       - in: query
 *         name: pageSize
 *         schema:
 *           type: integer
 *           default: 50
 *     responses:
 *       200:
 *         description: List of accounts
 *       401:
 *         $ref: '#/components/responses/Unauthorized'
 */
router.get('/accounts', zeroTrustAuthMiddleware, async (req, res, next) => {
  try {
    const result = await nostroVostroService.listAccounts({
      ownerParticipantId: req.query.ownerParticipantId as string,
      counterpartyParticipantId: req.query.counterpartyParticipantId as string,
      accountType: req.query.accountType as string,
      currency: req.query.currency as string,
      status: req.query.status as string,
      page: req.query.page ? parseInt(req.query.page as string) : undefined,
      pageSize: req.query.pageSize ? parseInt(req.query.pageSize as string) : undefined,
    });

    res.json({
      success: true,
      data: result,
      timestamp: new Date(),
    });
  } catch (error) {
      return next(error);
  }
});

/**
 * @swagger
 * /api/v1/nostro-vostro/accounts:
 *   post:
 *     summary: Create Nostro/Vostro account
 *     description: Create a new Nostro or Vostro account
 *     tags: [Nostro/Vostro]
 *     security:
 *       - SovereignToken: []
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             $ref: '#/components/schemas/AccountCreateRequest'
 *           example:
 *             ownerParticipantId: "PART-123"
 *             counterpartyParticipantId: "PART-456"
 *             ibanOrLocalAccount: "US64SVBKUS6S3300958879"
 *             currency: "USD"
 *             accountType: "NOSTRO"
 *     responses:
 *       201:
 *         description: Account created successfully
 *       400:
 *         $ref: '#/components/responses/BadRequest'
 *       404:
 *         $ref: '#/components/responses/NotFound'
 */
router.post('/accounts', zeroTrustAuthMiddleware, async (req, res, next) => {
  try {
    const account = await nostroVostroService.createAccount(req.body);

    res.status(201).json({
      success: true,
      data: account,
      timestamp: new Date(),
    });
  } catch (error) {
      return next(error);
  }
});

/**
 * @swagger
 * /api/v1/nostro-vostro/accounts/{accountId}:
 *   get:
 *     summary: Get account details
 *     description: Retrieve details for a specific account
 *     tags: [Nostro/Vostro]
 *     security:
 *       - SovereignToken: []
 *     parameters:
 *       - in: path
 *         name: accountId
 *         required: true
 *         schema:
 *           type: string
 *     responses:
 *       200:
 *         description: Account details
 *       404:
 *         $ref: '#/components/responses/NotFound'
 */
router.get('/accounts/:accountId', zeroTrustAuthMiddleware, async (req, res, next) => {
  try {
    const account = await nostroVostroService.getAccount(req.params.accountId);

    if (!account) {
      return res.status(404).json({
        success: false,
        error: { code: 'NOT_FOUND', message: 'Account not found' },
        timestamp: new Date(),
      });
    }

    res.json({
      success: true,
      data: account,
      timestamp: new Date(),
    });
  } catch (error) {
      return next(error);
  }
});

/**
 * @swagger
 * /api/v1/nostro-vostro/accounts/{accountId}/balances:
 *   get:
 *     summary: Get balances and liquidity
 *     description: Retrieve current balance, available liquidity, and hold amounts
 *     tags: [Nostro/Vostro]
 *     security:
 *       - SovereignToken: []
 *     parameters:
 *       - in: path
 *         name: accountId
 *         required: true
 *         schema:
 *           type: string
 *     responses:
 *       200:
 *         description: Balance details
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                 data:
 *                   $ref: '#/components/schemas/BalanceResponse'
 *       404:
 *         $ref: '#/components/responses/NotFound'
 */
router.get('/accounts/:accountId/balances', zeroTrustAuthMiddleware, async (req, res, next) => {
  try {
    const balances = await nostroVostroService.getAccountBalances(req.params.accountId);

    res.json({
      success: true,
      data: balances,
      timestamp: new Date(),
    });
  } catch (error) {
      return next(error);
  }
});

// ============================================================================
// Transfer Endpoints
// ============================================================================

/**
 * @swagger
 * /api/v1/nostro-vostro/transfers:
 *   post:
 *     summary: Initiate a transfer/settlement instruction
 *     description: Create a new transfer with idempotency support
 *     tags: [Nostro/Vostro]
 *     security:
 *       - SovereignToken: []
 *     parameters:
 *       - in: header
 *         name: Idempotency-Key
 *         required: false
 *         schema:
 *           type: string
 *         description: Idempotency key for duplicate request prevention
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             $ref: '#/components/schemas/TransferCreateRequest'
 *           example:
 *             fromAccountId: "ACC-123"
 *             toAccountId: "ACC-456"
 *             amount: "1000.00"
 *             currency: "USD"
 *             settlementAsset: "FIAT"
 *             valueDate: "2024-01-15"
 *             reference: "PAYMENT-REF-001"
 *     responses:
 *       201:
 *         description: Transfer created successfully
 *       400:
 *         $ref: '#/components/responses/BadRequest'
 *       409:
 *         description: Duplicate request (idempotency key conflict)
 *       422:
 *         $ref: '#/components/responses/UnprocessableEntity'
 */
router.post('/transfers', zeroTrustAuthMiddleware, async (req, res, next) => {
  try {
    const idempotencyKey = req.headers['idempotency-key'] as string | undefined;
    const transfer = await nostroVostroService.createTransfer(req.body, idempotencyKey);

    res.status(201).json({
      success: true,
      data: transfer,
      timestamp: new Date(),
    });
  } catch (error) {
      return next(error);
  }
});

/**
 * @swagger
 * /api/v1/nostro-vostro/transfers/{transferId}:
 *   get:
 *     summary: Get transfer status
 *     description: Retrieve transfer details and current status
 *     tags: [Nostro/Vostro]
 *     security:
 *       - SovereignToken: []
 *     parameters:
 *       - in: path
 *         name: transferId
 *         required: true
 *         schema:
 *           type: string
 *     responses:
 *       200:
 *         description: Transfer details
 *       404:
 *         $ref: '#/components/responses/NotFound'
 */
router.get('/transfers/:transferId', zeroTrustAuthMiddleware, async (req, res, next) => {
  try {
    const transfer = await nostroVostroService.getTransfer(req.params.transferId);

    if (!transfer) {
      return res.status(404).json({
        success: false,
        error: { code: 'NOT_FOUND', message: 'Transfer not found' },
        timestamp: new Date(),
      });
    }

    res.json({
      success: true,
      data: transfer,
      timestamp: new Date(),
    });
  } catch (error) {
      return next(error);
  }
});

/**
 * @swagger
 * /api/v1/nostro-vostro/transfers:
 *   get:
 *     summary: List transfers
 *     description: Retrieve a paginated list of transfers with optional filters
 *     tags: [Nostro/Vostro]
 *     security:
 *       - SovereignToken: []
 *     parameters:
 *       - in: query
 *         name: fromAccountId
 *         schema:
 *           type: string
 *       - in: query
 *         name: toAccountId
 *         schema:
 *           type: string
 *       - in: query
 *         name: status
 *         schema:
 *           type: string
 *           enum: [PENDING, ACCEPTED, SETTLED, REJECTED, CANCELLED]
 *       - in: query
 *         name: settlementAsset
 *         schema:
 *           type: string
 *           enum: [FIAT, GRU, SSU, CBDC]
 *       - in: query
 *         name: page
 *         schema:
 *           type: integer
 *           default: 1
 *       - in: query
 *         name: pageSize
 *         schema:
 *           type: integer
 *           default: 50
 *     responses:
 *       200:
 *         description: List of transfers
 */
router.get('/transfers', zeroTrustAuthMiddleware, async (req, res, next) => {
  try {
    const result = await nostroVostroService.listTransfers({
      fromAccountId: req.query.fromAccountId as string,
      toAccountId: req.query.toAccountId as string,
      fromParticipantId: req.query.fromParticipantId as string,
      toParticipantId: req.query.toParticipantId as string,
      status: req.query.status as string,
      settlementAsset: req.query.settlementAsset as string,
      page: req.query.page ? parseInt(req.query.page as string) : undefined,
      pageSize: req.query.pageSize ? parseInt(req.query.pageSize as string) : undefined,
    });

    res.json({
      success: true,
      data: result,
      timestamp: new Date(),
    });
  } catch (error) {
      return next(error);
  }
});

// ============================================================================
// Reconciliation Endpoints
// ============================================================================

/**
 * @swagger
 * /api/v1/nostro-vostro/reconciliations:
 *   post:
 *     summary: Request reconciliation report
 *     description: Generate a reconciliation report for a participant as of a specific date
 *     tags: [Nostro/Vostro]
 *     security:
 *       - SovereignToken: []
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             $ref: '#/components/schemas/ReconciliationRequest'
 *           example:
 *             participantId: "PART-123"
 *             asOfDate: "2024-01-15"
 *     responses:
 *       202:
 *         description: Reconciliation request accepted
 *       400:
 *         $ref: '#/components/responses/BadRequest'
 *       404:
 *         $ref: '#/components/responses/NotFound'
 */
router.post('/reconciliations', zeroTrustAuthMiddleware, async (req, res, next) => {
  try {
    const reconciliation = await reconciliationService.requestReconciliation(req.body);

    res.status(202).json({
      success: true,
      data: reconciliation,
      timestamp: new Date(),
    });
  } catch (error) {
      return next(error);
  }
});

/**
 * @swagger
 * /api/v1/nostro-vostro/reconciliations/{reportId}:
 *   get:
 *     summary: Get reconciliation report
 *     description: Retrieve a reconciliation report by ID
 *     tags: [Nostro/Vostro]
 *     security:
 *       - SovereignToken: []
 *     parameters:
 *       - in: path
 *         name: reportId
 *         required: true
 *         schema:
 *           type: string
 *     responses:
 *       200:
 *         description: Reconciliation report
 *       404:
 *         $ref: '#/components/responses/NotFound'
 */
router.get('/reconciliations/:reportId', zeroTrustAuthMiddleware, async (req, res, next) => {
  try {
    const reconciliation = await reconciliationService.getReconciliation(req.params.reportId);

    if (!reconciliation) {
      return res.status(404).json({
        success: false,
        error: { code: 'NOT_FOUND', message: 'Reconciliation report not found' },
        timestamp: new Date(),
      });
    }

    res.json({
      success: true,
      data: reconciliation,
      timestamp: new Date(),
    });
  } catch (error) {
      return next(error);
  }
});

// ============================================================================
// Webhook Endpoints
// ============================================================================

/**
 * @swagger
 * /api/v1/nostro-vostro/webhooks/subscriptions:
 *   post:
 *     summary: Create webhook subscription
 *     description: Subscribe to webhook events for a participant
 *     tags: [Nostro/Vostro]
 *     security:
 *       - SovereignToken: []
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             $ref: '#/components/schemas/WebhookSubscriptionCreateRequest'
 *           example:
 *             participantId: "PART-123"
 *             webhookUrl: "https://example.com/webhooks"
 *             eventTypes: ["TRANSFER_CREATED", "TRANSFER_SETTLED"]
 *     responses:
 *       201:
 *         description: Webhook subscription created
 *       400:
 *         $ref: '#/components/responses/BadRequest'
 */
router.post('/webhooks/subscriptions', zeroTrustAuthMiddleware, async (req, res, next) => {
  try {
    const subscription = await webhookService.createSubscription(req.body);

    res.status(201).json({
      success: true,
      data: subscription,
      timestamp: new Date(),
    });
  } catch (error) {
      return next(error);
  }
});

/**
 * @swagger
 * /api/v1/nostro-vostro/webhooks/subscriptions/{subscriptionId}:
 *   get:
 *     summary: Get webhook subscription
 *     description: Retrieve webhook subscription details
 *     tags: [Nostro/Vostro]
 *     security:
 *       - SovereignToken: []
 *     parameters:
 *       - in: path
 *         name: subscriptionId
 *         required: true
 *         schema:
 *           type: string
 *     responses:
 *       200:
 *         description: Webhook subscription details
 *       404:
 *         $ref: '#/components/responses/NotFound'
 */
router.get('/webhooks/subscriptions/:subscriptionId', zeroTrustAuthMiddleware, async (req, res, next) => {
  try {
    const subscription = await webhookService.getSubscription(req.params.subscriptionId);

    if (!subscription) {
      return res.status(404).json({
        success: false,
        error: { code: 'NOT_FOUND', message: 'Webhook subscription not found' },
        timestamp: new Date(),
      });
    }

    res.json({
      success: true,
      data: subscription,
      timestamp: new Date(),
    });
  } catch (error) {
      return next(error);
  }
});

/**
 * @swagger
 * /api/v1/nostro-vostro/webhooks/subscriptions:
 *   get:
 *     summary: List webhook subscriptions
 *     description: List webhook subscriptions for a participant
 *     tags: [Nostro/Vostro]
 *     security:
 *       - SovereignToken: []
 *     parameters:
 *       - in: query
 *         name: participantId
 *         required: true
 *         schema:
 *           type: string
 *       - in: query
 *         name: status
 *         schema:
 *           type: string
 *           enum: [ACTIVE, SUSPENDED, INACTIVE]
 *       - in: query
 *         name: page
 *         schema:
 *           type: integer
 *           default: 1
 *       - in: query
 *         name: pageSize
 *         schema:
 *           type: integer
 *           default: 50
 *     responses:
 *       200:
 *         description: List of webhook subscriptions
 */
router.get('/webhooks/subscriptions', zeroTrustAuthMiddleware, async (req, res, next) => {
  try {
    const participantId = req.query.participantId as string;
    if (!participantId) {
      return res.status(400).json({
        success: false,
        error: { code: 'VALIDATION_ERROR', message: 'participantId is required' },
        timestamp: new Date(),
      });
    }

    const result = await webhookService.listSubscriptions(participantId, {
      status: req.query.status as string,
      page: req.query.page ? parseInt(req.query.page as string) : undefined,
      pageSize: req.query.pageSize ? parseInt(req.query.pageSize as string) : undefined,
    });

    res.json({
      success: true,
      data: result,
      timestamp: new Date(),
    });
  } catch (error) {
      return next(error);
  }
});

/**
 * @swagger
 * /api/v1/nostro-vostro/webhooks/events:
 *   post:
 *     summary: Receive webhook events (FI side)
 *     description: Endpoint implemented by FI to receive notifications. This is a reference endpoint - FIs should implement their own.
 *     tags: [Nostro/Vostro]
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             properties:
 *               eventId:
 *                 type: string
 *               eventType:
 *                 type: string
 *               timestamp:
 *                 type: string
 *                 format: date-time
 *               payload:
 *                 type: object
 *     responses:
 *       200:
 *         description: Webhook event received
 */
router.post('/webhooks/events', async (req, res, next) => {
  // This is a reference endpoint - FIs should implement their own
  // We'll just acknowledge receipt
  res.json({
    success: true,
    message: 'Webhook event received',
    timestamp: new Date(),
  });
});

export default router;

