import { logger } from '@goodgo/logger';
import { initTracing } from '@goodgo/tracing';
import cors from 'cors';
import express from 'express';
import rateLimit from 'express-rate-limit';
import helmet from 'helmet';
import { RedisStore } from 'rate-limit-redis';

import { appConfig } from './config/app.config';
import { connectDatabase } from './config/database.config';
import { prisma } from './config/database.config';
import { getRedisClient } from './config/redis.config';
import { setupSwagger } from './docs/swagger';
import { correlationMiddleware } from './middlewares/correlation.middleware';
import { errorHandler, notFoundHandler } from './middlewares/error.middleware';
import { requestLogger } from './middlewares/logger.middleware';
import { metricsMiddleware } from './middlewares/metrics.middleware';
import { createRouter } from './routes';

// EN: Initialize tracing
// VI: Khởi tạo tracing
if (process.env.TRACING_ENABLED === 'true') {
  initTracing({
    serviceName: process.env.SERVICE_NAME || 'microservice',
    otlpEndpoint: process.env.OTLP_ENDPOINT,
    enabled: true,
  });
}

const app = express();

// EN: Security middleware
// VI: Middleware bảo mật
app.use(helmet());
app.use(
  cors({
    origin: appConfig.corsOrigin,
    credentials: true,
  })
);

// EN: Rate limiting
// VI: Giới hạn số lượng request
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 100,
  // EN: Use Redis for distributed rate limiting
  // VI: Sử dụng Redis để giới hạn rate phân tán
  store: new RedisStore({
    // @ts-expect-error - rate-limit-redis types mismatch with ioredis
    sendCommand: (...args: string[]) => getRedisClient().call(...args),
  }),

});
app.use('/api', limiter);

// EN: Correlation ID middleware (must be early)
// VI: Correlation ID middleware (phải đặt sớm)
app.use(correlationMiddleware());

// EN: Body parsing
// VI: Phân tích body request
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// EN: Request logging
// VI: Ghi log request
app.use(requestLogger);

// EN: Metrics
// VI: Metrics
app.use(metricsMiddleware);


// EN: Routes with async error handling
// VI: Routes với async error handling
app.use(createRouter());

// EN: Setup Swagger documentation
// VI: Thiết lập tài liệu Swagger
setupSwagger(app, '/api-docs');

// EN: Error handling
// VI: Xử lý lỗi
app.use(notFoundHandler);
app.use(errorHandler);

const startServer = async () => {
  try {
    await connectDatabase();

    const server = app.listen(appConfig.port, () => {
      logger.info(`Service started on port ${appConfig.port}`, {
        port: appConfig.port,
        nodeEnv: appConfig.nodeEnv,
      });
    });

    // EN: Graceful shutdown
    // VI: Đóng ứng dụng một cách an toàn
    const shutdown = async (signal: string) => {
      logger.info(`${signal} received, shutting down gracefully`);

      server.close(async () => {
        logger.info('HTTP server closed');

        try {
          await prisma.$disconnect();
          logger.info('Database connection closed');
          process.exit(0);
        } catch (error) {
          logger.error('Error during shutdown', { error });
          process.exit(1);
        }
      });

      // EN: Force shutdown after 10s
      // VI: Buộc dừng sau 10 giây
      setTimeout(() => {
        logger.error('Forcing shutdown after timeout');
        process.exit(1);
      }, 10000);
    };

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

  } catch (error) {
    logger.error('Failed to start server', { error });
    process.exit(1);
  }
};

startServer();
