const sqlite3 = require('sqlite3').verbose();
const path = require('path');
const fs = require('fs');

class DatabaseManager {
    constructor() {
        this.db = null;
    // Place database file under data/db
    this.dbPath = path.join(__dirname, '../data/db/image_uploader.db');
        this.schemaPath = path.join(__dirname, 'schema.sql');
    }

    async initialize() {
        try {
            // Stelle sicher, dass das data-Verzeichnis existiert
            const dataDir = path.dirname(this.dbPath);
            if (!fs.existsSync(dataDir)) {
                fs.mkdirSync(dataDir, { recursive: true });
            }

            // Öffne Datenbankverbindung
            this.db = new sqlite3.Database(this.dbPath, (err) => {
                if (err) {
                    console.error('Fehler beim Öffnen der Datenbank:', err.message);
                    throw err;
                } else {
                    console.log('✓ SQLite Datenbank verbunden:', this.dbPath);
                }
            });

            // Aktiviere Foreign Keys
            await this.run('PRAGMA foreign_keys = ON');
            
            // Erstelle Schema
            await this.createSchema();
            
            // Generate missing previews for existing images
            await this.generateMissingPreviews();
            
            console.log('✓ Datenbank erfolgreich initialisiert');
        } catch (error) {
            console.error('Fehler bei Datenbank-Initialisierung:', error);
            throw error;
        }
    }

    async createSchema() {
        try {
            console.log('🔨 Erstelle Datenbank-Schema...');
            
            // Erstelle Groups Tabelle
            await this.run(`
                CREATE TABLE IF NOT EXISTS groups (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    group_id TEXT UNIQUE NOT NULL,
                    year INTEGER NOT NULL,
                    title TEXT NOT NULL,
                    description TEXT,
                    name TEXT,
                    upload_date DATETIME NOT NULL,
                    approved BOOLEAN DEFAULT FALSE,
                    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
                )
            `);
            
            // Migration: Füge approved Feld zu bestehenden Tabellen hinzu (falls nicht vorhanden)
            try {
                await this.run('ALTER TABLE groups ADD COLUMN approved BOOLEAN DEFAULT FALSE');
                console.log('✓ Approved Feld zur bestehenden Tabelle hinzugefügt');
            } catch (error) {
                // Feld existiert bereits - das ist okay
                if (!error.message.includes('duplicate column')) {
                    console.warn('Migration Warnung:', error.message);
                }
            }
            console.log('✓ Groups Tabelle erstellt');

            // Erstelle Images Tabelle
            await this.run(`
                CREATE TABLE IF NOT EXISTS images (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    group_id TEXT NOT NULL,
                    file_name TEXT NOT NULL,
                    original_name TEXT NOT NULL,
                    file_path TEXT NOT NULL,
                    upload_order INTEGER NOT NULL,
                    file_size INTEGER,
                    mime_type TEXT,
                    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                    FOREIGN KEY (group_id) REFERENCES groups(group_id) ON DELETE CASCADE
                )
            `);
            console.log('✓ Images Tabelle erstellt');

            // Migration: Füge preview_path Feld zur images Tabelle hinzu (falls nicht vorhanden)
            try {
                await this.run('ALTER TABLE images ADD COLUMN preview_path TEXT');
                console.log('✓ preview_path Feld zur images Tabelle hinzugefügt');
            } catch (error) {
                // Feld existiert bereits - das ist okay
                if (!error.message.includes('duplicate column')) {
                    console.warn('Migration Warnung:', error.message);
                }
            }

            // Migration: Füge image_description Feld zur images Tabelle hinzu (falls nicht vorhanden)
            try {
                await this.run('ALTER TABLE images ADD COLUMN image_description TEXT');
                console.log('✓ image_description Feld zur images Tabelle hinzugefügt');
            } catch (error) {
                // Feld existiert bereits - das ist okay
                if (!error.message.includes('duplicate column')) {
                    console.warn('Migration Warnung:', error.message);
                }
            }

            // Erstelle Deletion Log Tabelle
            await this.run(`
                CREATE TABLE IF NOT EXISTS deletion_log (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    group_id TEXT NOT NULL,
                    year INTEGER NOT NULL,
                    image_count INTEGER NOT NULL,
                    upload_date DATETIME NOT NULL,
                    deleted_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                    deletion_reason TEXT DEFAULT 'auto_cleanup_7days',
                    total_file_size INTEGER
                )
            `);
            console.log('✓ Deletion Log Tabelle erstellt');

            // Erstelle Indizes
            await this.run('CREATE INDEX IF NOT EXISTS idx_groups_group_id ON groups(group_id)');
            await this.run('CREATE INDEX IF NOT EXISTS idx_groups_year ON groups(year)');
            await this.run('CREATE INDEX IF NOT EXISTS idx_groups_upload_date ON groups(upload_date)');
            await this.run('CREATE INDEX IF NOT EXISTS idx_groups_approved ON groups(approved)');
            await this.run('CREATE INDEX IF NOT EXISTS idx_groups_cleanup ON groups(approved, upload_date)');
            await this.run('CREATE INDEX IF NOT EXISTS idx_images_group_id ON images(group_id)');
            await this.run('CREATE INDEX IF NOT EXISTS idx_images_upload_order ON images(upload_order)');
            await this.run('CREATE INDEX IF NOT EXISTS idx_deletion_log_deleted_at ON deletion_log(deleted_at DESC)');
            await this.run('CREATE INDEX IF NOT EXISTS idx_deletion_log_year ON deletion_log(year)');
            console.log('✓ Indizes erstellt');

            // Erstelle Trigger
            await this.run(`
                CREATE TRIGGER IF NOT EXISTS update_groups_timestamp 
                AFTER UPDATE ON groups
                FOR EACH ROW
                BEGIN
                    UPDATE groups SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id;
                END
            `);
            console.log('✓ Trigger erstellt');
            
            console.log('✅ Datenbank-Schema vollständig erstellt');
        } catch (error) {
            console.error('💥 Fehler beim Erstellen des Schemas:', error);
            throw error;
        }
    }

    // Promise-wrapper für sqlite3.run
    run(sql, params = []) {
        return new Promise((resolve, reject) => {
            this.db.run(sql, params, function(err) {
                if (err) {
                    reject(err);
                } else {
                    resolve({ id: this.lastID, changes: this.changes });
                }
            });
        });
    }

    // Promise-wrapper für sqlite3.get
    get(sql, params = []) {
        return new Promise((resolve, reject) => {
            this.db.get(sql, params, (err, row) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(row);
                }
            });
        });
    }

    // Promise-wrapper für sqlite3.all
    all(sql, params = []) {
        return new Promise((resolve, reject) => {
            this.db.all(sql, params, (err, rows) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(rows);
                }
            });
        });
    }

    // Transaction support
    async transaction(callback) {
        await this.run('BEGIN TRANSACTION');
        try {
            const result = await callback(this);
            await this.run('COMMIT');
            return result;
        } catch (error) {
            await this.run('ROLLBACK');
            throw error;
        }
    }

    close() {
        return new Promise((resolve, reject) => {
            if (this.db) {
                this.db.close((err) => {
                    if (err) {
                        reject(err);
                    } else {
                        console.log('✓ Datenbankverbindung geschlossen');
                        resolve();
                    }
                });
            } else {
                resolve();
            }
        });
    }

    // Gesundheitscheck
    async healthCheck() {
        try {
            const result = await this.get('SELECT 1 as test');
            return result && result.test === 1;
        } catch (error) {
            console.error('Database health check failed:', error);
            return false;
        }
    }

    // Generate missing previews for existing images
    async generateMissingPreviews() {
        try {
            console.log('🔍 Checking for images without previews...');
            
            // Get all images that don't have a preview_path yet
            const imagesWithoutPreview = await this.all(`
                SELECT id, group_id, file_name, file_path 
                FROM images 
                WHERE preview_path IS NULL OR preview_path = ''
            `);

            if (imagesWithoutPreview.length === 0) {
                console.log('✓ All images have previews');
                return;
            }

            console.log(`📸 Found ${imagesWithoutPreview.length} image(s) without preview, generating...`);

            const ImagePreviewService = require('../services/ImagePreviewService');
            const fsp = require('fs').promises;
            let successCount = 0;
            let failCount = 0;

            for (const image of imagesWithoutPreview) {
                try {
                    // Check if original file exists
                    const originalPath = ImagePreviewService.getOriginalPath(image.file_name);
                    await fsp.access(originalPath);

                    // Generate preview
                    const previewFileName = ImagePreviewService._getPreviewFileName(image.file_name);
                    const previewPath = ImagePreviewService.getPreviewPath(previewFileName);
                    
                    const result = await ImagePreviewService.generatePreview(originalPath, previewPath);
                    
                    if (result.success) {
                        // Update database with preview_path
                        await this.run(`
                            UPDATE images 
                            SET preview_path = ? 
                            WHERE id = ?
                        `, [previewFileName, image.id]);
                        
                        successCount++;
                    } else {
                        console.warn(`  ⚠️  Preview generation failed for ${image.file_name}: ${result.error}`);
                        failCount++;
                    }
                } catch (error) {
                    console.warn(`  ⚠️  Could not process ${image.file_name}: ${error.message}`);
                    failCount++;
                }
            }

            console.log(`✓ Preview generation complete: ${successCount} success, ${failCount} failed`);
        } catch (error) {
            console.warn('⚠️  Preview generation check failed:', error.message);
            // Don't throw - this shouldn't prevent DB initialization
        }
    }
}

// Singleton Instance
const dbManager = new DatabaseManager();

module.exports = dbManager;