const express = require('express');
const fs = require('fs');
const path = require('path');
const initiateResources = require('./utils/initiate-resources');
const dbManager = require('./database/DatabaseManager');
const SchedulerService = require('./services/SchedulerService');
const TelegramNotificationService = require('./services/TelegramNotificationService');

// Singleton-Instanz des Telegram Service
const telegramService = new TelegramNotificationService();

// Dev: Swagger UI (mount only in non-production) — require lazily
let swaggerUi = null;
try {
    swaggerUi = require('swagger-ui-express');
} catch (e) {
    swaggerUi = null;
}

class Server {
    _port;
    _app;

    constructor(port) {
        this._port = port;
        this._app = express();
        const trustProxyHops = Number.parseInt(process.env.TRUST_PROXY_HOPS ?? '1', 10);
        if (!Number.isNaN(trustProxyHops) && trustProxyHops > 0) {
            this._app.set('trust proxy', trustProxyHops);
        }
    }

    async generateOpenApiSpecIfNeeded() {
        if (process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'test') {
            return;
        }

        try {
            const generateOpenApi = require('./generate-openapi');
            console.log('🔄 Generating OpenAPI specification...');
            await generateOpenApi();
            console.log('✓ OpenAPI spec generated');
        } catch (error) {
            console.warn('⚠️  Failed to generate OpenAPI spec:', error.message);
        }
    }

    loadSwaggerDocument() {
        try {
            const specPath = path.join(__dirname, '..', 'docs', 'openapi.json');
            const raw = fs.readFileSync(specPath, 'utf8');
            return JSON.parse(raw);
        } catch (error) {
            console.warn('⚠️  Unable to load Swagger document:', error.message);
            return null;
        }
    }

    async start() {
        try {
            await this.generateOpenApiSpecIfNeeded();

            // Initialisiere Datenbank
            console.log('🔄 Initialisiere Datenbank...');
            await dbManager.initialize();
            console.log('✓ Datenbank bereit');

            // Starte Express Server
            initiateResources(this._app);
            this._app.use('/upload', express.static( __dirname + '/upload'));
            this._app.use('/api/previews', express.static( __dirname + '/data/previews'));

            // Mount Swagger UI in dev only when available
            if (process.env.NODE_ENV !== 'production' && swaggerUi) {
                const swaggerDocument = this.loadSwaggerDocument();
                if (swaggerDocument) {
                    this._app.use('/api/docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
                    console.log('ℹ️  Swagger UI mounted at /api/docs (dev only)');
                }
            }
            this._app.listen(this._port, () => {
                console.log(`✅ Server läuft auf Port ${this._port}`);
                console.log(`📊 SQLite Datenbank aktiv`);
                
                // Speichere SchedulerService in app für Admin-Endpoints
                this._app.set('schedulerService', SchedulerService);
                
                // Starte Scheduler für automatisches Cleanup
                SchedulerService.start();

                // Teste Telegram-Service (optional, nur in Development wenn aktiviert)
                if (process.env.NODE_ENV === 'development' 
                    && process.env.TELEGRAM_SEND_TEST_ON_START === 'true' 
                    && telegramService.isAvailable()) {
                    telegramService.sendTestMessage()
                        .catch(err => console.error('[Telegram] Test message failed:', err.message));
                }
            });
        } catch (error) {
            console.error('💥 Fehler beim Serverstart:', error);
            process.exit(1);
        }
    }

    // Expose app for testing
    getApp() {
        return this._app;
    }

    // Initialize app without listening (for tests)
    async initializeApp() {
        await dbManager.initialize();
        initiateResources(this._app);
        this._app.use('/upload', express.static( __dirname + '/upload'));
        this._app.use('/api/previews', express.static( __dirname + '/data/previews'));
        
        if (process.env.NODE_ENV !== 'production' && swaggerUi) {
            const swaggerDocument = this.loadSwaggerDocument();
            if (swaggerDocument) {
                this._app.use('/api/docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
            }
        }
        return this._app;
    }
}

module.exports = Server;