import express, { Application, Request, Response } from 'express';
import cors from 'cors';
import helmet from 'helmet';
import rateLimit from 'express-rate-limit';
import swaggerUi from 'swagger-ui-express';
import { config } from './config';
import { logger } from './config/logger';
import { errorHandler } from './middleware/errorHandler';
import { RegisterRoutes } from './routes/routes';

export function createApp(): Application {
    const app = express();

    // Security middleware - Disable CSP for Swagger UI
    app.use(helmet({
        contentSecurityPolicy: false
    }));

    // CORS - Allow multiple origins
    const allowedOrigins = config.cors.origin.split(',').map(o => o.trim());
    app.use(cors({
        origin: (origin, callback) => {
            // Allow requests with no origin (like mobile apps, Postman, curl)
            if (!origin) return callback(null, true);

            // Check if origin is allowed
            if (allowedOrigins.includes('*') || allowedOrigins.includes(origin)) {
                callback(null, true);
            } else {
                callback(new Error('Not allowed by CORS'));
            }
        },
        credentials: true
    }));

    // Rate limiting
    const limiter = rateLimit({
        windowMs: config.rateLimit.windowMs,
        max: config.rateLimit.maxRequests,
        message: {
            error: {
                code: 'RATE_LIMIT_EXCEEDED',
                message: 'Too many requests, please try again later'
            }
        }
    });
    app.use('/api/', limiter);

    // Body parsing
    app.use(express.json());
    app.use(express.urlencoded({ extended: true }));

    // Request logging
    app.use((req: Request, res: Response, next) => {
        logger.info('Incoming request', {
            method: req.method,
            path: req.path,
            ip: req.ip
        });
        next();
    });

    // Swagger documentation
    try {
        const swaggerDocument = require('../public/swagger.json');
        app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
        logger.info('Swagger documentation available at /api-docs');
    } catch (error) {
        logger.warn('Swagger documentation not available. Run "npm run tsoa:gen" to generate it.');
    }

    // Simple health check endpoint (not using TSOA)
    app.get('/health', (req: Request, res: Response) => {
        res.json({
            status: 'ok',
            timestamp: new Date().toISOString(),
            uptime: process.uptime()
        });
    });

    // Register TSOA routes
    RegisterRoutes(app);

    // 404 handler
    app.use((req: Request, res: Response) => {
        res.status(404).json({
            error: {
                code: 'NOT_FOUND',
                message: 'Route not found'
            }
        });
    });

    // Error handler (must be last)
    app.use(errorHandler);

    return app;
}
