// api-keys.js - API для управления ключами доступа к задачам с логированием

const express = require('express');
const crypto = require('crypto');
const path = require('path');
const fs = require('fs');
const router = express.Router();

module.exports = function(app, db, upload) {
    
    // Middleware для проверки аутентификации
    const requireAuth = (req, res, next) => {
        if (!req.session || !req.session.user) {
            return res.status(401).json({ error: 'Требуется аутентификация' });
        }
        next();
    };

    // Middleware для проверки прав администратора
    const requireAdmin = (req, res, next) => {
        if (!req.session || !req.session.user || req.session.user.role !== 'admin') {
            return res.status(403).json({ error: 'Недостаточно прав' });
        }
        next();
    };

    // Функция для логирования действий API
    const logApiAction = (apiKeyId, userId, action, details, req, statusCode = 200, responseTime = 0) => {
        const timestamp = new Date().toISOString();
        const ip = req.ip || req.connection.remoteAddress;
        const userAgent = req.get('User-Agent') || 'Unknown';
        
        const logEntry = {
            timestamp,
            api_key_id: apiKeyId,
            user_id: userId,
            action,
            details,
            ip,
            user_agent: userAgent,
            method: req.method,
            path: req.originalUrl,
            status_code: statusCode,
            response_time: responseTime
        };

        // Цветное логирование в консоль
        const colors = {
            GET: '\x1b[32m',    // зеленый
            POST: '\x1b[33m',   // желтый
            PUT: '\x1b[34m',    // синий
            DELETE: '\x1b[31m', // красный
            reset: '\x1b[0m'
        };

        const methodColor = colors[req.method] || '\x1b[36m';
        
        console.log('\n' + '='.repeat(50));
        console.log(`${methodColor}🔑 API ${req.method} ${req.originalUrl}${colors.reset}`);
        console.log(`📅 ${timestamp}`);
        console.log(`👤 Пользователь: ID ${userId} (${req.apiUser?.name || 'Unknown'})`);
        console.log(`🔑 API Key ID: ${apiKeyId}`);
        console.log(`📋 Действие: ${action}`);
        console.log(`📝 Детали: ${details}`);
        console.log(`🌐 IP: ${ip}`);
        console.log(`📱 User-Agent: ${userAgent.substring(0, 50)}...`);
        console.log(`📊 Статус: ${statusCode} | Время: ${responseTime}ms`);
        console.log('='.repeat(50));

        // Сохраняем в базу данных
        db.run(`
            INSERT INTO api_logs (
                api_key_id, user_id, action, details, ip, user_agent, 
                method, path, response_status, response_time, created_at
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        `, [
            apiKeyId, userId, action, details, ip, userAgent, 
            req.method, req.originalUrl, statusCode, responseTime, timestamp
        ], (err) => {
            if (err) {
                console.error('❌ Ошибка сохранения лога API:', err.message);
            }
        });

        // Логируем в общую активность для важных действий
        const { logActivity } = require('./database');
        if (logActivity && (
            action.includes('STATUS') || 
            action.includes('FILE') || 
            action.includes('CREATE') ||
            action.includes('UPDATE') ||
            action.includes('DELETE')
        )) {
            const taskId = extractTaskIdFromDetails(details) || extractTaskIdFromUrl(req.originalUrl);
            if (taskId) {
                logActivity(
                    taskId, 
                    userId, 
                    `API_${action}`,
                    `[API Key ${apiKeyId}] ${details}`
                );
            }
        }
    };

    // Вспомогательная функция для извлечения ID задачи из деталей
    function extractTaskIdFromDetails(details) {
        const match = details.match(/задачи?\s*[#№]?\s*(\d+)/i);
        return match ? parseInt(match[1]) : null;
    }

    // Вспомогательная функция для извлечения ID задачи из URL
    function extractTaskIdFromUrl(url) {
        const match = url.match(/\/tasks?\/(\d+)/i);
        return match ? parseInt(match[1]) : null;
    }

    // Функция для логирования попыток аутентификации
    const logApiAttempt = (apiKeyId, userId, action, details, req, statusCode, responseTime) => {
        const timestamp = new Date().toISOString();
        const ip = req.ip || req.connection.remoteAddress;
        const userAgent = req.get('User-Agent') || 'Unknown';
        
        const color = statusCode >= 400 ? '\x1b[31m' : '\x1b[33m';
        
        console.log('\n' + '='.repeat(50));
        console.log(`${color}🔑 API ATTEMPT ${req.method} ${req.originalUrl}${'\x1b[0m'}`);
        console.log(`📅 ${timestamp}`);
        console.log(`👤 Пользователь ID: ${userId || 'N/A'}`);
        console.log(`🔑 API Key ID: ${apiKeyId || 'N/A'}`);
        console.log(`📋 Действие: ${action}`);
        console.log(`📝 Детали: ${details}`);
        console.log(`🌐 IP: ${ip}`);
        console.log(`📊 Статус: ${statusCode} | Время: ${responseTime}ms`);
        console.log('='.repeat(50));

        if (apiKeyId && userId) {
            db.run(`
                INSERT INTO api_logs (
                    api_key_id, user_id, action, details, ip, user_agent, 
                    method, path, response_status, response_time, created_at
                ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            `, [
                apiKeyId, userId, action, details, ip, userAgent, 
                req.method, req.originalUrl, statusCode, responseTime, timestamp
            ], (err) => {
                if (err) {
                    console.error('❌ Ошибка сохранения лога попытки:', err.message);
                }
            });
        }
    };

    // Создание таблиц для API ключей и логов
function createApiKeysTables() {
    return new Promise((resolve, reject) => {
        // Таблица API ключей
        db.run(`
            CREATE TABLE IF NOT EXISTS api_keys (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                name TEXT NOT NULL,
                key TEXT NOT NULL UNIQUE,
                user_id INTEGER NOT NULL,
                description TEXT,
                allowed_ips TEXT,
                is_active BOOLEAN DEFAULT true,
                last_used_at DATETIME,
                last_used_ip TEXT,
                created_by INTEGER NOT NULL,
                created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
                FOREIGN KEY (created_by) REFERENCES users(id)
            )
        `, (err) => {
            if (err) {
                console.error('❌ Ошибка создания таблицы api_keys:', err.message);
                reject(err);
                return;
            }

            // Проверяем и добавляем отсутствующие колонки
            db.all("PRAGMA table_info(api_keys)", (err, columns) => {
                if (err) {
                    console.error('❌ Ошибка получения информации о таблице:', err);
                } else {
                    const columnNames = columns.map(c => c.name);
                    
                    // Добавляем last_used_ip если отсутствует
                    if (!columnNames.includes('last_used_ip')) {
                        db.run("ALTER TABLE api_keys ADD COLUMN last_used_ip TEXT", (err) => {
                            if (err) {
                                console.error('❌ Ошибка добавления колонки last_used_ip:', err.message);
                            } else {
                                console.log('✅ Добавлена колонка last_used_ip в таблицу api_keys');
                            }
                        });
                    }
                }
            });

            // Таблица для логов API действий
            db.run(`
                CREATE TABLE IF NOT EXISTS api_logs (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    api_key_id INTEGER NOT NULL,
                    user_id INTEGER NOT NULL,
                    action TEXT NOT NULL,
                    details TEXT,
                    ip TEXT,
                    user_agent TEXT,
                    method TEXT,
                    path TEXT,
                    response_status INTEGER,
                    response_time INTEGER,
                    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                    FOREIGN KEY (api_key_id) REFERENCES api_keys(id) ON DELETE CASCADE,
                    FOREIGN KEY (user_id) REFERENCES users(id)
                )
            `, (err) => {
                if (err) {
                    console.error('❌ Ошибка создания таблицы api_logs:', err.message);
                    reject(err);
                    return;
                }

                // Таблица для связи API ключей с задачами
                db.run(`
                    CREATE TABLE IF NOT EXISTS api_task_mappings (
                        id INTEGER PRIMARY KEY AUTOINCREMENT,
                        api_key_id INTEGER NOT NULL,
                        task_id INTEGER NOT NULL,
                        external_task_id TEXT,
                        synced_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                        last_status TEXT,
                        FOREIGN KEY (api_key_id) REFERENCES api_keys(id) ON DELETE CASCADE,
                        FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE,
                        UNIQUE(api_key_id, task_id)
                    )
                `, (err) => {
                    if (err) {
                        console.error('❌ Ошибка создания таблицы api_task_mappings:', err.message);
                        reject(err);
                        return;
                    }

                    // Индексы
                    db.run('CREATE INDEX IF NOT EXISTS idx_api_keys_user_id ON api_keys(user_id)');
                    db.run('CREATE INDEX IF NOT EXISTS idx_api_keys_key ON api_keys(key)');
                    db.run('CREATE INDEX IF NOT EXISTS idx_api_logs_api_key_id ON api_logs(api_key_id)');
                    db.run('CREATE INDEX IF NOT EXISTS idx_api_logs_created_at ON api_logs(created_at)');
                    db.run('CREATE INDEX IF NOT EXISTS idx_api_task_mappings_task_id ON api_task_mappings(task_id)');
                    
                    console.log('✅ Таблицы для API ключей и логов созданы');
                    resolve();
                });
            });
        });
    });
}

    // Генерация уникального API ключа
    function generateApiKey() {
        return crypto.randomBytes(32).toString('hex');
    }

    // Middleware для проверки API ключа с логированием
    const requireApiKey = (req, res, next) => {
        const startTime = Date.now();
        const apiKey = req.headers['x-api-key'] || req.query.api_key;
        const ip = req.ip || req.connection.remoteAddress;
        
        console.log('\n\x1b[33m%s\x1b[0m', '🔑 Входящий API запрос');
        console.log('🌐 IP:', ip);
        console.log('🔑 Ключ:', apiKey ? apiKey.substring(0, 8) + '...' : 'не предоставлен');
        console.log('🔄 Метод:', req.method);
        console.log('📍 Путь:', req.originalUrl);
        
        if (!apiKey) {
            logApiAttempt(null, null, 'AUTH_FAILED', 'Ключ не предоставлен', req, 401, Date.now() - startTime);
            return res.status(401).json({ error: 'API ключ обязателен' });
        }

        // Проверяем ключ в базе
        db.get(`
            SELECT ak.*, u.login as user_login, u.name as user_name, u.id as user_id
            FROM api_keys ak
            JOIN users u ON ak.user_id = u.id
            WHERE ak.key = ? AND ak.is_active = 1
        `, [apiKey], (err, keyData) => {
            const responseTime = Date.now() - startTime;
            
            if (err) {
                console.error('❌ Ошибка проверки ключа:', err);
                logApiAttempt(null, null, 'AUTH_ERROR', `Ошибка БД: ${err.message}`, req, 500, responseTime);
                return res.status(500).json({ error: 'Ошибка проверки ключа' });
            }
            
            if (!keyData) {
                console.log('❌ Недействительный ключ:', apiKey.substring(0, 8) + '...');
                
                // Проверяем, есть ли такой ключ в базе (неактивный)
                db.get('SELECT is_active FROM api_keys WHERE key = ?', [apiKey], (err, inactiveKey) => {
                    const reason = inactiveKey ? 'Ключ деактивирован' : 'Ключ не найден';
                    logApiAttempt(null, null, 'AUTH_FAILED', reason, req, 401, responseTime);
                });
                
                return res.status(401).json({ error: 'Недействительный API ключ' });
            }

            // Проверка IP, если настроено
            if (keyData.allowed_ips) {
                try {
                    const allowedIPs = JSON.parse(keyData.allowed_ips);
                    if (allowedIPs.length > 0 && !allowedIPs.includes(ip)) {
                        console.log('❌ IP не разрешен:', ip);
                        logApiAttempt(keyData.id, keyData.user_id, 'AUTH_FAILED', `IP ${ip} не разрешен`, req, 403, responseTime);
                        return res.status(403).json({ error: 'IP адрес не разрешен' });
                    }
                } catch (e) {
                    console.error('Ошибка парсинга allowed_ips:', e);
                }
            }

            // Обновляем информацию о последнем использовании
            db.run(
                'UPDATE api_keys SET last_used_at = CURRENT_TIMESTAMP, last_used_ip = ? WHERE id = ?',
                [ip, keyData.id]
            );

            console.log('✅ Ключ валидный. Пользователь:', keyData.user_name);
            console.log('⏱️ Время проверки:', responseTime + 'ms');

            req.apiKey = keyData;
            req.apiUser = {
                id: keyData.user_id,
                login: keyData.user_login,
                name: keyData.user_name
            };

            // Сохраняем startTime для логирования времени ответа
            req.apiRequestStartTime = startTime;
            
            next();
        });
    };

    // Middleware для логирования ответов
    const logResponse = (req, res, next) => {
        const originalJson = res.json;
        const originalSend = res.send;
        const startTime = req.apiRequestStartTime || Date.now();

        res.json = function(data) {
            const responseTime = Date.now() - startTime;
            
            if (req.apiKey) {
                logApiAction(
                    req.apiKey.id,
                    req.apiUser.id,
                    `${req.method}_${req.path.replace(/[^a-zA-Z0-9]/g, '_')}`,
                    `Статус: ${res.statusCode}`,
                    req,
                    res.statusCode,
                    responseTime
                );
            }
            
            console.log(`📤 Ответ отправлен за ${responseTime}ms`);
            originalJson.call(this, data);
        };

        res.send = function(data) {
            const responseTime = Date.now() - startTime;
            
            if (req.apiKey) {
                logApiAction(
                    req.apiKey.id,
                    req.apiUser.id,
                    `${req.method}_${req.path.replace(/[^a-zA-Z0-9]/g, '_')}`,
                    `Статус: ${res.statusCode}`,
                    req,
                    res.statusCode,
                    responseTime
                );
            }
            
            console.log(`📤 Ответ отправлен за ${responseTime}ms`);
            originalSend.call(this, data);
        };

        next();
    };

    // GET /api/api-keys/logs - Получить логи API (только админ)
    router.get('/api/api-keys/logs', requireAuth, requireAdmin, (req, res) => {
        const { limit = 100, offset = 0, api_key_id, user_id, action } = req.query;

        let query = `
            SELECT l.*, ak.name as api_key_name, u.name as user_name, u.login as user_login
            FROM api_logs l
            LEFT JOIN api_keys ak ON l.api_key_id = ak.id
            LEFT JOIN users u ON l.user_id = u.id
            WHERE 1=1
        `;
        const params = [];

        if (api_key_id) {
            query += ' AND l.api_key_id = ?';
            params.push(api_key_id);
        }

        if (user_id) {
            query += ' AND l.user_id = ?';
            params.push(user_id);
        }

        if (action) {
            query += ' AND l.action LIKE ?';
            params.push(`%${action}%`);
        }

        query += ' ORDER BY l.created_at DESC LIMIT ? OFFSET ?';
        params.push(parseInt(limit), parseInt(offset));

        db.all(query, params, (err, logs) => {
            if (err) {
                console.error('❌ Ошибка получения логов:', err);
                return res.status(500).json({ error: 'Ошибка получения логов' });
            }

            // Получаем общее количество
            db.get('SELECT COUNT(*) as total FROM api_logs', [], (err, count) => {
                if (err) {
                    return res.json({ logs: logs || [], total: 0 });
                }

                res.json({
                    success: true,
                    logs: logs || [],
                    total: count.total,
                    limit: parseInt(limit),
                    offset: parseInt(offset)
                });
            });
        });
    });

    // GET /api/api-keys/:id/logs - Получить логи конкретного ключа
    router.get('/api/api-keys/:id/logs', requireAuth, requireAdmin, (req, res) => {
        const { id } = req.params;
        const { limit = 50 } = req.query;

        db.all(`
            SELECT l.*, u.name as user_name
            FROM api_logs l
            LEFT JOIN users u ON l.user_id = u.id
            WHERE l.api_key_id = ?
            ORDER BY l.created_at DESC
            LIMIT ?
        `, [id, parseInt(limit)], (err, logs) => {
            if (err) {
                console.error('❌ Ошибка получения логов ключа:', err);
                return res.status(500).json({ error: 'Ошибка получения логов' });
            }

            res.json({
                success: true,
                logs: logs || []
            });
        });
    });

    // GET /api/api-keys/stats - Статистика использования API
    router.get('/api/api-keys/stats', requireAuth, requireAdmin, (req, res) => {
        const stats = {};

        // Общая статистика
        db.get(`
            SELECT 
                COUNT(DISTINCT api_key_id) as active_keys,
                COUNT(*) as total_requests,
                COUNT(DISTINCT user_id) as unique_users,
                AVG(response_time) as avg_response_time,
                COUNT(CASE WHEN response_status >= 400 THEN 1 END) as error_count,
                COUNT(CASE WHEN DATE(created_at) = DATE('now') THEN 1 END) as today_requests
            FROM api_logs
            WHERE created_at >= DATE('now', '-30 days')
        `, [], (err, total) => {
            if (err) {
                console.error('❌ Ошибка получения статистики:', err);
                return res.status(500).json({ error: 'Ошибка получения статистики' });
            }

            stats.total = total || {};

            // Статистика по методам
            db.all(`
                SELECT method, COUNT(*) as count
                FROM api_logs
                WHERE created_at >= DATE('now', '-30 days')
                GROUP BY method
                ORDER BY count DESC
            `, [], (err, methods) => {
                if (err) {
                    return res.json(stats);
                }

                stats.by_method = methods || [];

                // Статистика по дням
                db.all(`
                    SELECT DATE(created_at) as date, COUNT(*) as count
                    FROM api_logs
                    WHERE created_at >= DATE('now', '-7 days')
                    GROUP BY DATE(created_at)
                    ORDER BY date DESC
                `, [], (err, daily) => {
                    if (err) {
                        return res.json(stats);
                    }

                    stats.daily = daily || [];

                    // Топ ключей
                    db.all(`
                        SELECT 
                            l.api_key_id,
                            ak.name as api_key_name,
                            COUNT(*) as request_count,
                            COUNT(DISTINCT l.user_id) as users_count,
                            AVG(l.response_time) as avg_time
                        FROM api_logs l
                        LEFT JOIN api_keys ak ON l.api_key_id = ak.id
                        WHERE l.created_at >= DATE('now', '-30 days')
                        GROUP BY l.api_key_id
                        ORDER BY request_count DESC
                        LIMIT 10
                    `, [], (err, topKeys) => {
                        if (err) {
                            return res.json(stats);
                        }

                        stats.top_keys = topKeys || [];

                        res.json({
                            success: true,
                            stats,
                            timestamp: new Date().toISOString()
                        });
                    });
                });
            });
        });
    });

    // GET /api/api-keys - Получить все ключи (только админ)
    router.get('/api/api-keys', requireAuth, requireAdmin, (req, res) => {
        db.all(`
            SELECT ak.*, u.name as user_name, u.login as user_login,
                   creator.name as creator_name,
                   (SELECT COUNT(*) FROM api_logs WHERE api_key_id = ak.id) as request_count,
                   (SELECT created_at FROM api_logs WHERE api_key_id = ak.id ORDER BY created_at DESC LIMIT 1) as last_request
            FROM api_keys ak
            LEFT JOIN users u ON ak.user_id = u.id
            LEFT JOIN users creator ON ak.created_by = creator.id
            ORDER BY ak.created_at DESC
        `, [], (err, keys) => {
            if (err) {
                console.error('❌ Ошибка получения API ключей:', err);
                return res.status(500).json({ error: 'Ошибка получения ключей' });
            }
            
            // Маскируем ключи для безопасности
            const maskedKeys = (keys || []).map(key => ({
                ...key,
                key: key.key.substring(0, 8) + '...' + key.key.substring(key.key.length - 8),
                request_count: key.request_count || 0
            }));
            
            res.json(maskedKeys);
        });
    });

    // POST /api/api-keys - Создать новый API ключ (только админ)
    router.post('/api/api-keys', requireAuth, requireAdmin, (req, res) => {
        const { name, user_id, description, allowed_ips } = req.body;
        const startTime = Date.now();

        if (!name || !user_id) {
            return res.status(400).json({ error: 'Название и пользователь обязательны' });
        }

        // Проверяем существование пользователя
        db.get('SELECT id, name FROM users WHERE id = ?', [user_id], (err, user) => {
            if (err || !user) {
                return res.status(404).json({ error: 'Пользователь не найден' });
            }

            const apiKey = generateApiKey();
            const allowedIPsJson = allowed_ips ? JSON.stringify(allowed_ips.split(',').map(ip => ip.trim())) : null;

            db.run(`
                INSERT INTO api_keys (name, key, user_id, description, allowed_ips, created_by)
                VALUES (?, ?, ?, ?, ?, ?)
            `, [name, apiKey, user_id, description || '', allowedIPsJson, req.session.user.id],
            function(err) {
                const responseTime = Date.now() - startTime;
                
                if (err) {
                    console.error('❌ Ошибка создания API ключа:', err);
                    return res.status(500).json({ error: 'Ошибка создания ключа' });
                }

                // Логируем создание ключа
                logApiAction(
                    this.lastID,
                    req.session.user.id,
                    'API_KEY_CREATED',
                    `Создан ключ "${name}" для пользователя ${user.name} (ID: ${user_id})`,
                    req,
                    201,
                    responseTime
                );

                res.status(201).json({
                    success: true,
                    id: this.lastID,
                    key: apiKey,
                    message: 'API ключ успешно создан'
                });
            });
        });
    });

    // PUT /api/api-keys/:id/toggle - Активировать/деактивировать ключ
    router.put('/api/api-keys/:id/toggle', requireAuth, requireAdmin, (req, res) => {
        const { id } = req.params;
        const { is_active } = req.body;
        const startTime = Date.now();

        db.get('SELECT name FROM api_keys WHERE id = ?', [id], (err, key) => {
            if (err || !key) {
                return res.status(404).json({ error: 'Ключ не найден' });
            }

            db.run(
                'UPDATE api_keys SET is_active = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?',
                [is_active ? 1 : 0, id],
                function(err) {
                    const responseTime = Date.now() - startTime;
                    
                    if (err) {
                        console.error('❌ Ошибка обновления ключа:', err);
                        return res.status(500).json({ error: 'Ошибка обновления ключа' });
                    }

                    logApiAction(
                        id,
                        req.session.user.id,
                        is_active ? 'API_KEY_ACTIVATED' : 'API_KEY_DEACTIVATED',
                        `Ключ "${key.name}" ${is_active ? 'активирован' : 'деактивирован'}`,
                        req,
                        200,
                        responseTime
                    );

                    res.json({ 
                        success: true, 
                        message: `Ключ ${is_active ? 'активирован' : 'деактивирован'}` 
                    });
                }
            );
        });
    });

    // DELETE /api/api-keys/:id - Удалить ключ (только админ)
    router.delete('/api/api-keys/:id', requireAuth, requireAdmin, (req, res) => {
        const { id } = req.params;
        const startTime = Date.now();

        db.get('SELECT name FROM api_keys WHERE id = ?', [id], (err, key) => {
            if (err || !key) {
                return res.status(404).json({ error: 'Ключ не найден' });
            }

            db.run('DELETE FROM api_keys WHERE id = ?', [id], function(err) {
                const responseTime = Date.now() - startTime;
                
                if (err) {
                    console.error('❌ Ошибка удаления ключа:', err);
                    return res.status(500).json({ error: 'Ошибка удаления ключа' });
                }

                logApiAction(
                    id,
                    req.session.user.id,
                    'API_KEY_DELETED',
                    `Удален ключ "${key.name}"`,
                    req,
                    200,
                    responseTime
                );

                res.json({ success: true, message: 'Ключ удален' });
            });
        });
    });

    // ==================== Публичное API для внешних сервисов ====================

    // GET /api/external/tasks - Получить задачи для внешнего сервиса
    router.get('/api/external/tasks', requireApiKey, logResponse, (req, res) => {
        const userId = req.apiUser.id;
        const { status, limit = 50, offset = 0 } = req.query;
        const startTime = Date.now();

        let query = `
            SELECT DISTINCT
                t.id,
                t.title,
                t.description,
                t.created_at,
                t.due_date,
                t.task_type,
                u.name as creator_name,
                (
                    SELECT json_group_array(json_object(
                        'id', tf.id,
                        'filename', tf.original_name,
                        'file_size', tf.file_size,
                        'uploaded_at', tf.uploaded_at
                    ))
                    FROM task_files tf
                    WHERE tf.task_id = t.id
                ) as files,
                ta.status as assignment_status,
                ta.start_date,
                ta.due_date as assignment_due_date
            FROM tasks t
            LEFT JOIN users u ON t.created_by = u.id
            LEFT JOIN task_assignments ta ON t.id = ta.task_id AND ta.user_id = ?
            WHERE ta.user_id = ? 
            AND t.status = 'active'
            AND t.closed_at IS NULL
        `;

        const params = [userId, userId];

        if (status) {
            if (status === 'active') {
                query += ` AND ta.status IN ('assigned', 'in_progress')`;
            } else {
                query += ` AND ta.status = ?`;
                params.push(status);
            }
        }

        query += ` ORDER BY t.due_date ASC, t.created_at DESC LIMIT ? OFFSET ?`;
        params.push(limit, offset);

        db.all(query, params, (err, tasks) => {
            const responseTime = Date.now() - startTime;
            
            if (err) {
                console.error('❌ Ошибка получения задач:', err);
                logApiAction(
                    req.apiKey.id,
                    userId,
                    'GET_TASKS_ERROR',
                    `Ошибка: ${err.message}`,
                    req,
                    500,
                    responseTime
                );
                return res.status(500).json({ error: 'Ошибка получения задач' });
            }

            // Парсим JSON с файлами
            const result = (tasks || []).map(task => {
                try {
                    task.files = JSON.parse(task.files || '[]');
                } catch (e) {
                    task.files = [];
                }
                return task;
            });

            logApiAction(
                req.apiKey.id,
                userId,
                'GET_TASKS',
                `Получено ${result.length} задач${status ? ` (статус: ${status})` : ''}`,
                req,
                200,
                responseTime
            );

            res.json({
                success: true,
                tasks: result,
                meta: {
                    total: result.length,
                    limit,
                    offset,
                    user: req.apiUser.name
                }
            });
        });
    });

    // GET /api/external/tasks/:taskId - Получить конкретную задачу
    router.get('/api/external/tasks/:taskId', requireApiKey, logResponse, (req, res) => {
        const { taskId } = req.params;
        const userId = req.apiUser.id;
        const startTime = Date.now();

        // Проверяем, что задача назначена этому пользователю
        db.get(`
            SELECT t.*, u.name as creator_name,
                   (
                       SELECT json_group_array(json_object(
                           'id', tf.id,
                           'filename', tf.original_name,
                           'file_path', tf.file_path,
                           'file_size', tf.file_size,
                           'uploaded_at', tf.uploaded_at,
                           'uploader_name', up.name
                       ))
                       FROM task_files tf
                       LEFT JOIN users up ON tf.user_id = up.id
                       WHERE tf.task_id = t.id
                   ) as files,
                   ta.status as assignment_status,
                   ta.start_date,
                   ta.due_date as assignment_due_date
            FROM tasks t
            LEFT JOIN users u ON t.created_by = u.id
            LEFT JOIN task_assignments ta ON t.id = ta.task_id AND ta.user_id = ?
            WHERE t.id = ? AND ta.user_id IS NOT NULL
        `, [userId, taskId], (err, task) => {
            const responseTime = Date.now() - startTime;
            
            if (err) {
                console.error('❌ Ошибка получения задачи:', err);
                logApiAction(
                    req.apiKey.id,
                    userId,
                    'GET_TASK_ERROR',
                    `Ошибка получения задачи ${taskId}: ${err.message}`,
                    req,
                    500,
                    responseTime
                );
                return res.status(500).json({ error: 'Ошибка получения задачи' });
            }
            
            if (!task) {
                logApiAction(
                    req.apiKey.id,
                    userId,
                    'GET_TASK_NOT_FOUND',
                    `Задача ${taskId} не найдена или не назначена`,
                    req,
                    404,
                    responseTime
                );
                return res.status(404).json({ error: 'Задача не найдена или не назначена вам' });
            }

            try {
                task.files = JSON.parse(task.files || '[]');
            } catch (e) {
                task.files = [];
            }

            logApiAction(
                req.apiKey.id,
                userId,
                'GET_TASK',
                `Получена задача ${taskId}: "${task.title}"`,
                req,
                200,
                responseTime
            );

            res.json({ success: true, task });
        });
    });

    // PUT /api/external/tasks/:taskId/status - Изменить статус задачи
    router.put('/api/external/tasks/:taskId/status', requireApiKey, logResponse, (req, res) => {
        const { taskId } = req.params;
        const { status, comment } = req.body;
        const userId = req.apiUser.id;
        const startTime = Date.now();

        if (!status || !['in_progress', 'completed'].includes(status)) {
            logApiAction(
                req.apiKey.id,
                userId,
                'UPDATE_STATUS_ERROR',
                `Попытка установить недопустимый статус "${status}" для задачи ${taskId}`,
                req,
                400,
                Date.now() - startTime
            );
            return res.status(400).json({ 
                error: 'Статус должен быть "in_progress" или "completed"' 
            });
        }

        // Проверяем, что задача назначена этому пользователю
        db.get(`
            SELECT ta.id, ta.status as current_status, t.title, t.created_by
            FROM task_assignments ta
            JOIN tasks t ON ta.task_id = t.id
            WHERE ta.task_id = ? AND ta.user_id = ?
        `, [taskId, userId], (err, assignment) => {
            if (err || !assignment) {
                const responseTime = Date.now() - startTime;
                logApiAction(
                    req.apiKey.id,
                    userId,
                    'UPDATE_STATUS_ERROR',
                    `Задача ${taskId} не назначена пользователю`,
                    req,
                    404,
                    responseTime
                );
                return res.status(404).json({ error: 'Задача не назначена вам' });
            }

            // Обновляем статус
            db.run(
                `UPDATE task_assignments 
                 SET status = ?, updated_at = CURRENT_TIMESTAMP 
                 WHERE task_id = ? AND user_id = ?`,
                [status, taskId, userId],
                function(err) {
                    const responseTime = Date.now() - startTime;
                    
                    if (err) {
                        console.error('❌ Ошибка обновления статуса:', err);
                        logApiAction(
                            req.apiKey.id,
                            userId,
                            'UPDATE_STATUS_ERROR',
                            `Ошибка обновления статуса задачи ${taskId}: ${err.message}`,
                            req,
                            500,
                            responseTime
                        );
                        return res.status(500).json({ error: 'Ошибка обновления статуса' });
                    }

                    const details = `Статус задачи ${taskId} "${assignment.title}" изменен с ${assignment.current_status} на ${status}. Комментарий: ${comment || 'нет'}`;
                    
                    logApiAction(
                        req.apiKey.id,
                        userId,
                        `TASK_${status.toUpperCase()}`,
                        details,
                        req,
                        200,
                        responseTime
                    );

                    // Логируем в общую активность
                    const { logActivity } = require('./database');
                    if (logActivity) {
                        logActivity(
                            parseInt(taskId), 
                            userId, 
                            `API_TASK_${status.toUpperCase()}`, 
                            `[API Key ${req.apiKey.id}] ${comment || 'Без комментария'}`
                        );
                    }

                    res.json({ 
                        success: true, 
                        message: `Статус изменен на "${status}"`,
                        old_status: assignment.current_status,
                        new_status: status,
                        task_title: assignment.title
                    });
                }
            );
        });
    });

    // POST /api/external/tasks/:taskId/files - Загрузить файл к задаче
    router.post('/api/external/tasks/:taskId/files', requireApiKey, logResponse, upload.single('file'), (req, res) => {
        const { taskId } = req.params;
        const userId = req.apiUser.id;
        const startTime = Date.now();

        if (!req.file) {
            logApiAction(
                req.apiKey.id,
                userId,
                'UPLOAD_FILE_ERROR',
                `Попытка загрузить файл без файла к задаче ${taskId}`,
                req,
                400,
                Date.now() - startTime
            );
            return res.status(400).json({ error: 'Файл обязателен' });
        }

        // Проверяем, что задача назначена этому пользователю
        db.get(`
            SELECT ta.id, t.title
            FROM task_assignments ta
            JOIN tasks t ON ta.task_id = t.id
            WHERE ta.task_id = ? AND ta.user_id = ?
        `, [taskId, userId], (err, assignment) => {
            if (err || !assignment) {
                // Удаляем загруженный файл, если он не нужен
                if (req.file && req.file.path && fs.existsSync(req.file.path)) {
                    fs.unlinkSync(req.file.path);
                }
                
                const responseTime = Date.now() - startTime;
                logApiAction(
                    req.apiKey.id,
                    userId,
                    'UPLOAD_FILE_ERROR',
                    `Задача ${taskId} не назначена пользователю`,
                    req,
                    404,
                    responseTime
                );
                return res.status(404).json({ error: 'Задача не назначена вам' });
            }

            const { createUserTaskFolder } = require('./database');
            const userFolder = createUserTaskFolder(taskId, req.apiUser.login);

            const newPath = path.join(userFolder, path.basename(req.file.filename));
            fs.renameSync(req.file.path, newPath);

            db.run(
                `INSERT INTO task_files 
                 (task_id, user_id, filename, original_name, file_path, file_size) 
                 VALUES (?, ?, ?, ?, ?, ?)`,
                [taskId, userId, path.basename(req.file.filename), req.file.originalname, newPath, req.file.size],
                function(err) {
                    const responseTime = Date.now() - startTime;
                    
                    if (err) {
                        console.error('❌ Ошибка сохранения файла:', err);
                        logApiAction(
                            req.apiKey.id,
                            userId,
                            'UPLOAD_FILE_ERROR',
                            `Ошибка сохранения файла для задачи ${taskId}: ${err.message}`,
                            req,
                            500,
                            responseTime
                        );
                        return res.status(500).json({ error: 'Ошибка сохранения файла' });
                    }

                    const details = `Загружен файл "${req.file.originalname}" (${(req.file.size / 1024).toFixed(2)} KB) к задаче ${taskId} "${assignment.title}"`;
                    
                    logApiAction(
                        req.apiKey.id,
                        userId,
                        'FILE_UPLOADED',
                        details,
                        req,
                        200,
                        responseTime
                    );

                    // Логируем в общую активность
                    const { logActivity } = require('./database');
                    if (logActivity) {
                        logActivity(
                            parseInt(taskId), 
                            userId, 
                            'API_FILE_UPLOADED', 
                            `[API Key ${req.apiKey.id}] Загружен файл: ${req.file.originalname}`
                        );
                    }

                    res.json({
                        success: true,
                        file_id: this.lastID,
                        filename: req.file.originalname,
                        size: req.file.size,
                        message: 'Файл успешно загружен'
                    });
                }
            );
        });
    });

    // GET /api/external/tasks/:taskId/files/:fileId/download - Скачать файл
    router.get('/api/external/tasks/:taskId/files/:fileId/download', requireApiKey, logResponse, (req, res) => {
        const { taskId, fileId } = req.params;
        const userId = req.apiUser.id;
        const startTime = Date.now();

        db.get(`
            SELECT tf.*, t.title as task_title
            FROM task_files tf
            JOIN task_assignments ta ON tf.task_id = ta.task_id
            JOIN tasks t ON tf.task_id = t.id
            WHERE tf.id = ? AND tf.task_id = ? AND ta.user_id = ?
        `, [fileId, taskId, userId], (err, file) => {
            const responseTime = Date.now() - startTime;
            
            if (err || !file) {
                logApiAction(
                    req.apiKey.id,
                    userId,
                    'DOWNLOAD_FILE_ERROR',
                    `Файл ${fileId} не найден для задачи ${taskId}`,
                    req,
                    404,
                    responseTime
                );
                return res.status(404).json({ error: 'Файл не найден' });
            }

            if (!fs.existsSync(file.file_path)) {
                logApiAction(
                    req.apiKey.id,
                    userId,
                    'DOWNLOAD_FILE_ERROR',
                    `Файл ${fileId} не найден на сервере для задачи ${taskId}`,
                    req,
                    404,
                    responseTime
                );
                return res.status(404).json({ error: 'Файл не найден на сервере' });
            }

            logApiAction(
                req.apiKey.id,
                userId,
                'FILE_DOWNLOADED',
                `Скачан файл "${file.original_name}" из задачи ${taskId} "${file.task_title}"`,
                req,
                200,
                responseTime
            );

            res.setHeader('Content-Disposition', `attachment; filename*=UTF-8''${encodeURIComponent(file.original_name)}`);
            res.setHeader('Content-Type', 'application/octet-stream');
            res.sendFile(file.file_path);
        });
    });

    // ==================== Инициализация ====================
    
    const init = async () => {
        try {
            await createApiKeysTables();
            console.log('✅ Модуль API ключей с логированием инициализирован');
        } catch (error) {
            console.error('❌ Ошибка инициализации API ключей:', error.message);
        }
    };

    init();
    
    app.use(router);

    return {
        requireApiKey,
        generateApiKey
    };
};