const BlockedDevice = require('../models/BlockedDevice');

/**
 * Middleware для проверки блокировки устройства
 * Должен использоваться перед аутентификацией
 */
const checkDeviceBlock = async (req, res, next) => {
  try {
    console.log('[DEVICE_CHECK] Проверка блокировки устройства');
    
    // Получаем fingerprint устройства из заголовков запроса
    const deviceFingerprint = req.headers['x-device-fingerprint'];
    
    if (!deviceFingerprint) {
      console.log('[DEVICE_CHECK] Device fingerprint не предоставлен');
      return res.status(400).json({
        message: 'Требуется идентификация устройства для обеспечения безопасности',
        code: 'DEVICE_FINGERPRINT_REQUIRED'
      });
    }

    console.log('[DEVICE_CHECK] Проверяем fingerprint:', deviceFingerprint.substring(0, 16) + '...');

    // Проверяем, заблокировано ли устройство
    const blockedDevice = await BlockedDevice.isDeviceBlocked(deviceFingerprint);
    
    if (blockedDevice) {
      console.log('[DEVICE_CHECK] Устройство заблокировано:', {
        deviceId: blockedDevice._id,
        blockedAt: blockedDevice.blockedAt,
        reason: blockedDevice.reason
      });

      // Записываем попытку обхода блокировки
      await blockedDevice.addBypassAttempt({
        type: req.route?.path?.includes('/login') ? 'login' : 
              req.route?.path?.includes('/register') ? 'register' : 'api_request',
        ipAddress: req.ip || req.connection.remoteAddress,
        userAgent: req.headers['user-agent']
      });

      // Возвращаем ошибку блокировки
      return res.status(403).json({
        blocked: true,
        message: 'Доступ с данного устройства заблокирован',
        reason: blockedDevice.reason,
        blockedAt: blockedDevice.blockedAt,
        code: 'DEVICE_BLOCKED'
      });
    }

    // Проверяем похожие заблокированные устройства
    const similarDevices = await BlockedDevice.findSimilarDevices(deviceFingerprint, 0.85);
    
    if (similarDevices.length > 0) {
      console.log('[DEVICE_CHECK] Найдены похожие заблокированные устройства:', similarDevices.length);
      
      // Повышаем уровень безопасности для похожих устройств
      req.securityRisk = 'HIGH';
      req.similarBlockedDevices = similarDevices;
      
      // Можно добавить дополнительные проверки для подозрительных устройств
      // Например, CAPTCHA или дополнительную верификацию
    }

    // Сохраняем fingerprint в запросе для дальнейшего использования
    req.deviceFingerprint = deviceFingerprint;
    req.deviceInfo = {
      userAgent: req.headers['user-agent'],
      ipAddress: req.ip || req.connection.remoteAddress,
      screenResolution: req.headers['x-screen-resolution'],
      platform: req.headers['x-platform'],
      language: req.headers['x-language'],
      timezone: req.headers['x-timezone']
    };

    console.log('[DEVICE_CHECK] Устройство не заблокировано, продолжаем');
    next();
    
  } catch (error) {
    console.error('[DEVICE_CHECK] Ошибка при проверке блокировки устройства:', error);
    
    // В случае ошибки системы безопасности, блокируем доступ
    return res.status(500).json({
      message: 'Ошибка системы безопасности. Попробуйте позже.',
      code: 'SECURITY_CHECK_ERROR'
    });
  }
};

/**
 * Middleware для записи информации об устройстве при успешной аутентификации
 */
const recordDeviceActivity = async (req, res, next) => {
  try {
    if (req.deviceFingerprint && req.user) {
      console.log('[DEVICE_RECORD] Записываем активность устройства для пользователя:', req.user._id);
      
      // Можно сохранить информацию об устройстве пользователя для анализа
      // Например, в отдельной коллекции UserDevices
      
      // Пока просто логируем
      console.log('[DEVICE_RECORD] Device fingerprint:', req.deviceFingerprint.substring(0, 16) + '...');
      console.log('[DEVICE_RECORD] Device info:', req.deviceInfo);
    }
    
    next();
  } catch (error) {
    console.error('[DEVICE_RECORD] Ошибка при записи активности устройства:', error);
    // Не блокируем запрос из-за ошибки записи
    next();
  }
};

/**
 * Функция для блокировки устройства пользователя
 */
const blockUserDevice = async (userId, adminId, reason, deviceFingerprint = null) => {
  try {
    console.log('[BLOCK_DEVICE] Блокировка устройства пользователя:', userId);
    
    if (!deviceFingerprint) {
      // Если fingerprint не предоставлен, нужно найти его в активных сессиях
      // Это более сложная задача, требующая отслеживания активных сессий
      throw new Error('Device fingerprint не предоставлен для блокировки');
    }

    const deviceInfo = {
      // Получаем дополнительную информацию об устройстве из базы данных или сессии
      // Это может быть реализовано через отслеживание активных подключений
    };

    const blockedDevice = await BlockedDevice.blockDevice({
      deviceFingerprint,
      blockedBy: adminId,
      blockedUserId: userId,
      reason,
      deviceInfo
    });

    console.log('[BLOCK_DEVICE] Устройство заблокировано:', blockedDevice._id);
    return blockedDevice;
    
  } catch (error) {
    console.error('[BLOCK_DEVICE] Ошибка при блокировке устройства:', error);
    throw error;
  }
};

/**
 * Функция для разблокировки устройства
 */
const unblockDevice = async (deviceFingerprint, adminId, reason) => {
  try {
    console.log('[UNBLOCK_DEVICE] Разблокировка устройства:', deviceFingerprint.substring(0, 16) + '...');
    
    const blockedDevice = await BlockedDevice.findOne({
      deviceFingerprint,
      isActive: true
    });

    if (!blockedDevice) {
      throw new Error('Заблокированное устройство не найдено');
    }

    await blockedDevice.unblock(adminId, reason);
    
    console.log('[UNBLOCK_DEVICE] Устройство разблокировано');
    return blockedDevice;
    
  } catch (error) {
    console.error('[UNBLOCK_DEVICE] Ошибка при разблокировке устройства:', error);
    throw error;
  }
};

/**
 * Функция для получения информации о заблокированных устройствах
 */
const getBlockedDevices = async (filters = {}) => {
  try {
    const {
      page = 1,
      limit = 20,
      sortBy = 'blockedAt',
      sortOrder = 'desc',
      isActive = true,
      userId
    } = filters;

    const query = { isActive };
    
    if (userId) {
      query.blockedUserId = userId;
    }

    const skip = (page - 1) * limit;
    const sort = { [sortBy]: sortOrder === 'desc' ? -1 : 1 };

    const devices = await BlockedDevice.find(query)
      .populate('blockedBy', 'name email')
      .populate('blockedUserId', 'name email')
      .sort(sort)
      .skip(skip)
      .limit(limit);

    const total = await BlockedDevice.countDocuments(query);

    return {
      devices,
      pagination: {
        currentPage: page,
        totalPages: Math.ceil(total / limit),
        totalItems: total,
        itemsPerPage: limit
      }
    };
    
  } catch (error) {
    console.error('[GET_BLOCKED_DEVICES] Ошибка при получении заблокированных устройств:', error);
    throw error;
  }
};

module.exports = {
  checkDeviceBlock,
  recordDeviceActivity,
  blockUserDevice,
  unblockDevice,
  getBlockedDevices
};