/**
 * eResidency Service
 * Handles eResidency application, vetting, and credential issuance
 */

import Fastify from 'fastify';
import fastifySwagger from '@fastify/swagger';
import fastifySwaggerUI from '@fastify/swagger-ui';
import {
  errorHandler,
  createLogger,
  registerSecurityPlugins,
  addCorrelationId,
  addRequestLogging,
  getEnv,
} from '@the-order/shared';
import { getPool } from '@the-order/database';

const logger = createLogger('eresidency-service');

const server = Fastify({
  logger: true,
  requestIdLogLabel: 'requestId',
  disableRequestLogging: false,
});

// Initialize database pool
const env = getEnv();
if (env.DATABASE_URL) {
  getPool({ connectionString: env.DATABASE_URL });
}

// Initialize server
async function initializeServer(): Promise<void> {
  // Register Swagger
  const swaggerUrl = env.SWAGGER_SERVER_URL || (env.NODE_ENV === 'development' ? 'http://localhost:4003' : undefined);
  if (!swaggerUrl) {
    logger.warn('SWAGGER_SERVER_URL not set, Swagger documentation will not be available');
  } else {
    await server.register(fastifySwagger, {
      openapi: {
        info: {
          title: 'eResidency Service API',
          description: 'eResidency application, vetting, and credential issuance',
          version: '1.0.0',
        },
        servers: [
          {
            url: swaggerUrl,
            description: env.NODE_ENV || 'Development server',
          },
        ],
      },
    });

    await server.register(fastifySwaggerUI, {
      routePrefix: '/docs',
    });
  }

  // Register security plugins
  await registerSecurityPlugins(server);

  // Add middleware
  addCorrelationId(server);
  addRequestLogging(server);

  // Set error handler
  server.setErrorHandler(errorHandler);

  // Register application flow routes
  const { registerApplicationFlowRoutes } = await import('./application-flow');
  const { KMSClient } = await import('@the-order/crypto');
  const kmsClient = new KMSClient({
    provider: env.KMS_TYPE || 'aws',
    keyId: env.KMS_KEY_ID,
    region: env.KMS_REGION,
  });
  await registerApplicationFlowRoutes(server, {
    kmsClient,
    kycProvider: 'veriff',
    sanctionsProvider: 'complyadvantage',
  });

  // Register reviewer console routes
  const { registerReviewerConsoleRoutes } = await import('./reviewer-console');
  await registerReviewerConsoleRoutes(server);

  // Register status endpoint
  const { registerStatusEndpoint } = await import('./status-endpoint');
  await registerStatusEndpoint(server);

  // Initialize auto-issuance service
  if (env.REDIS_URL) {
    try {
      const { initializeAutoIssuance } = await import('./auto-issuance');
      await initializeAutoIssuance({
        kmsClient,
        autoIssueOnApproval: true,
      });
      logger.info('Auto-issuance service initialized');
    } catch (error) {
      logger.warn('Failed to initialize auto-issuance service:', error);
    }
  }
}

// Health check
server.get(
  '/health',
  {
    schema: {
      description: 'Health check endpoint',
      tags: ['health'],
      response: {
        200: {
          type: 'object',
          properties: {
            status: { type: 'string' },
            service: { type: 'string' },
            database: { type: 'string' },
          },
        },
      },
    },
  },
  async () => {
    const { healthCheck: dbHealthCheck } = await import('@the-order/database');
    const dbHealthy = await dbHealthCheck().catch(() => false);

    return {
      status: dbHealthy ? 'ok' : 'degraded',
      service: 'eresidency',
      database: dbHealthy ? 'connected' : 'disconnected',
    };
  }
);

// Start server
async function start(): Promise<void> {
  try {
    await initializeServer();
    const port = env.PORT || 4003;
    await server.listen({ port, host: '0.0.0.0' });
    logger.info(`eResidency service listening on port ${port}`);
  } catch (error) {
    logger.error('Failed to start server:', error);
    process.exit(1);
  }
}

// Handle shutdown
process.on('SIGTERM', async () => {
  logger.info('SIGTERM received, shutting down gracefully');
  await server.close();
  process.exit(0);
});

process.on('SIGINT', async () => {
  logger.info('SIGINT received, shutting down gracefully');
  await server.close();
  process.exit(0);
});

if (require.main === module) {
  start();
}

export default server;

