const mongoose = require('mongoose');
const User = require('../models/User');
const Conversation = require('../models/Conversation');
const Message = require('../models/Message');
const ProfileView = require('../models/ProfileView');

/**
 * @desc    Получить список всех пользователей
 * @route   GET /api/admin/users
 * @access  Admin
 */
const getAllUsers = async (req, res) => {
  try {
    const { search, page = 1, limit = 20, isActive } = req.query;
    const skip = (page - 1) * limit;

    // Создание фильтра
    const filter = {};
    
    // Добавляем поиск по имени или email, если указан
    if (search) {
      filter.$or = [
        { name: { $regex: search, $options: 'i' } },
        { email: { $regex: search, $options: 'i' } }
      ];
    }

    // Фильтр по статусу активности, если указан
    if (isActive !== undefined) {
      filter.isActive = isActive === 'true';
    }

    // Исключаем админа из результатов выдачи
    filter.isAdmin = { $ne: true };

    // Получаем пользователей с пагинацией
    const users = await User.find(filter)
      .select('-password')
      .skip(skip)
      .limit(parseInt(limit))
      .sort({ createdAt: -1 });

    // Получаем общее количество пользователей для пагинации
    const total = await User.countDocuments(filter);

    res.json({
      users,
      pagination: {
        page: parseInt(page),
        limit: parseInt(limit),
        total,
        pages: Math.ceil(total / limit)
      }
    });
  } catch (error) {
    console.error('Ошибка при получении списка пользователей:', error);
    res.status(500).json({ message: 'Ошибка сервера при получении списка пользователей' });
  }
};

/**
 * @desc    Получить детальную информацию о пользователе
 * @route   GET /api/admin/users/:id
 * @access  Admin
 */
const getUserDetails = async (req, res) => {
  try {
    const userId = req.params.id;
    
    const user = await User.findById(userId)
      .select('-password')
      .lean();
    
    if (!user) {
      return res.status(404).json({ message: 'Пользователь не найден' });
    }

    // Получаем статистику для пользователя
    const messagesCount = await Message.countDocuments({ sender: userId });
    const conversationsCount = await Conversation.countDocuments({ 
      participants: userId 
    });
    const profileViewsCount = await ProfileView.countDocuments({ 
      profileOwner: userId 
    });
    const matchesCount = user.matches ? user.matches.length : 0;
    const likesGivenCount = user.liked ? user.liked.length : 0;

    // Добавляем статистику к данным пользователя
    const userWithStats = {
      ...user,
      stats: {
        messagesCount,
        conversationsCount,
        profileViewsCount,
        matchesCount,
        likesGivenCount
      }
    };

    res.json(userWithStats);
  } catch (error) {
    console.error('Ошибка при получении информации о пользователе:', error);
    res.status(500).json({ message: 'Ошибка сервера при получении информации о пользователе' });
  }
};

/**
 * @desc    Заблокировать/разблокировать пользователя
 * @route   PUT /api/admin/users/:id/toggle-active
 * @access  Admin
 */
const toggleUserActive = async (req, res) => {
  try {
    const userId = req.params.id;
    const { reason } = req.body; // Добавляем возможность указать причину блокировки
    const user = await User.findById(userId);
    
    if (!user) {
      return res.status(404).json({ message: 'Пользователь не найден' });
    }

    // Проверка, чтобы нельзя было заблокировать админа
    if (user.isAdmin) {
      return res.status(403).json({ message: 'Невозможно заблокировать администратора' });
    }

    // Получаем доступ к io для отправки уведомлений
    const io = req.app.get('io');
    if (!io) {
      console.error('[AdminController] Ошибка: экземпляр Socket.IO не доступен через req.app.get("io")');
      return res.status(500).json({ message: 'Внутренняя ошибка сервера: Socket.IO недоступен' });
    }

    // Изменяем статус активности на противоположный
    const wasActive = user.isActive;
    user.isActive = !user.isActive;
    await user.save();
    
    // Получаем глобальный массив активных пользователей из server.js
    // Это напрямую обращается к глобальной переменной в server.js
    const activeUsers = req.app.get('activeUsers') || [];
    
    console.log(`[AdminController] Активные пользователи:`, activeUsers);
    
    // Если пользователь был активным и теперь блокируется
    if (wasActive && !user.isActive) {
      console.log(`[AdminController] Блокировка пользователя ${userId}. Причина: ${reason || 'Не указана'}`);
      
      // Ищем пользователя среди активных пользователей
      const userSockets = activeUsers.filter(u => u.userId === userId);
      console.log(`[AdminController] Найдено активных записей пользователя: ${userSockets.length}`);

      if (userSockets.length > 0) {
        userSockets.forEach(userSocket => {
          try {
            const socket = io.sockets.sockets.get(userSocket.socketId);
            if (socket) {
              console.log(`[AdminController] Отправка уведомления о блокировке на сокет: ${userSocket.socketId}`);
              socket.emit("account_blocked", {
                message: 'Ваш аккаунт был заблокирован администратором.',
                reason: reason || 'Нарушение правил сервиса',
                timestamp: new Date().toISOString(),
                blocked: true
              });
              
              // Принудительно отключаем сокет
              setTimeout(() => {
                try {
                  console.log(`[AdminController] Принудительное отключение сокета: ${userSocket.socketId}`);
                  socket.disconnect(true);
                } catch (socketError) {
                  console.error(`[AdminController] Ошибка при отключении сокета ${userSocket.socketId}:`, socketError);
                }
              }, 500);
            } else {
              console.log(`[AdminController] Не найден объект сокета для ID: ${userSocket.socketId}`);
            }
          } catch (socketError) {
            console.error(`[AdminController] Ошибка при обработке сокета ${userSocket.socketId}:`, socketError);
          }
        });
      } else {
        console.log(`[AdminController] Пользователь ${userId} не найден в активных соединениях`);
      }
    }
    // Если пользователь был неактивным и теперь разблокируется
    else if (!wasActive && user.isActive) {
      console.log(`[AdminController] Разблокировка пользователя ${userId}`);
      
      // Ищем пользователя среди активных пользователей (на случай, если он онлайн с другим аккаунтом)
      const userSockets = activeUsers.filter(u => u.userId === userId);
      
      if (userSockets.length > 0) {
        userSockets.forEach(userSocket => {
          try {
            const socket = io.sockets.sockets.get(userSocket.socketId);
            if (socket) {
              console.log(`[AdminController] Отправка уведомления о разблокировке на сокет: ${userSocket.socketId}`);
              socket.emit("account_unblocked", {
                message: 'Ваш аккаунт был разблокирован администратором.',
                timestamp: new Date().toISOString()
              });
            } else {
              console.log(`[AdminController] Не найден объект сокета для ID: ${userSocket.socketId}`);
            }
          } catch (socketError) {
            console.error(`[AdminController] Ошибка при обработке сокета ${userSocket.socketId}:`, socketError);
          }
        });
      } else {
        console.log(`[AdminController] Пользователь ${userId} не найден в активных соединениях для отправки уведомления о разблокировке`);
      }
    }

    res.json({ 
      message: user.isActive ? 'Пользователь разблокирован' : 'Пользователь заблокирован',
      isActive: user.isActive
    });
  } catch (error) {
    console.error('Ошибка при изменении статуса пользователя:', error);
    res.status(500).json({ message: 'Ошибка сервера при изменении статуса пользователя' });
  }
};

/**
 * @desc    Получить статистику приложения
 * @route   GET /api/admin/statistics
 * @access  Admin
 */
const getAppStatistics = async (req, res) => {
  try {
    // Общая статистика пользователей
    const totalUsers = await User.countDocuments({ isAdmin: { $ne: true } });
    const activeUsers = await User.countDocuments({ isActive: true, isAdmin: { $ne: true } });
    const inactiveUsers = await User.countDocuments({ isActive: false, isAdmin: { $ne: true } });
    
    // Статистика по полу
    const maleUsers = await User.countDocuments({ gender: 'male' });
    const femaleUsers = await User.countDocuments({ gender: 'female' });
    const otherGenderUsers = await User.countDocuments({ gender: 'other' });
    
    // Статистика сообщений и диалогов
    const totalMessages = await Message.countDocuments();
    const totalConversations = await Conversation.countDocuments();
    
    // Статистика просмотров профилей
    const totalProfileViews = await ProfileView.countDocuments();
    
    // Средние значения
    const messagesPerUser = totalUsers > 0 ? totalMessages / totalUsers : 0;
    const conversationsPerUser = totalUsers > 0 ? totalConversations / totalUsers : 0;
    
    // Новые пользователи за последние 30 дней
    const thirtyDaysAgo = new Date();
    thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
    
    const newUsers30Days = await User.countDocuments({ 
      createdAt: { $gte: thirtyDaysAgo },
      isAdmin: { $ne: true }
    });
    
    res.json({
      users: {
        total: totalUsers,
        active: activeUsers,
        inactive: inactiveUsers,
        newIn30Days: newUsers30Days,
        genderDistribution: {
          male: maleUsers,
          female: femaleUsers,
          other: otherGenderUsers
        }
      },
      activity: {
        totalMessages,
        totalConversations,
        totalProfileViews,
        averages: {
          messagesPerUser: messagesPerUser.toFixed(2),
          conversationsPerUser: conversationsPerUser.toFixed(2)
        }
      }
    });
  } catch (error) {
    console.error('Ошибка при получении статистики приложения:', error);
    res.status(500).json({ message: 'Ошибка сервера при получении статистики приложения' });
  }
};

/**
 * @desc    Получить список всех диалогов
 * @route   GET /api/admin/conversations
 * @access  Admin
 */
const getAllConversations = async (req, res) => {
  try {
    console.log('[ADMIN] Запрос списка диалогов');
    const { page = 1, limit = 20, userId } = req.query;
    const skip = (page - 1) * limit;
    
    // Создание фильтра
    const filter = {};
    
    // Фильтр по пользователю, если указан
    if (userId) {
      console.log(`[ADMIN] Фильтр по пользователю: ${userId}`);
      if (!mongoose.Types.ObjectId.isValid(userId)) {
        console.log(`[ADMIN] Недопустимый формат ID пользователя: ${userId}`);
        return res.status(400).json({ message: 'Недопустимый формат ID пользователя' });
      }
      filter.participants = userId;
    }
    
    console.log(`[ADMIN] Поиск диалогов с фильтром:`, filter);
    
    // Получаем диалоги с пагинацией и данными участников
    const conversations = await Conversation.find(filter)
      .populate('participants', 'name email photos')
      .populate('lastMessage')
      .skip(skip)
      .limit(parseInt(limit))
      .sort({ updatedAt: -1 });
    
    console.log(`[ADMIN] Найдено диалогов: ${conversations.length}`);
    
    // Получаем общее количество диалогов для пагинации
    const total = await Conversation.countDocuments(filter);
    
    // Добавляем дополнительную информацию о диалогах
    const conversationsWithInfo = conversations.map(conv => {
      const convObj = conv.toObject();
      convObj._id = convObj._id.toString(); // Преобразуем ObjectId в строку для безопасности
      return convObj;
    });
    
    res.json({
      conversations: conversationsWithInfo,
      pagination: {
        page: parseInt(page),
        limit: parseInt(limit),
        total,
        pages: Math.ceil(total / limit)
      }
    });
  } catch (error) {
    console.error('[ADMIN] Ошибка при получении списка диалогов:', error);
    res.status(500).json({ message: 'Ошибка сервера при получении списка диалогов' });
  }
};

/**
 * @desc    Получить сообщения диалога
 * @route   GET /api/admin/conversations/:id/messages
 * @access  Admin
 */
const getConversationMessages = async (req, res) => {
  try {
    const conversationId = req.params.id;
    console.log(`[ADMIN] Запрос сообщений для диалога с ID: ${conversationId}`);
    
    if (!mongoose.Types.ObjectId.isValid(conversationId)) {
      console.log(`[ADMIN] Недопустимый формат ID диалога: ${conversationId}`);
      return res.status(400).json({ message: 'Недопустимый формат ID диалога' });
    }
    
    const { page = 1, limit = 50 } = req.query;
    const skip = (page - 1) * limit;
    
    // Проверяем существование диалога с подробным логированием
    console.log(`[ADMIN] Поиск диалога с ID: ${conversationId}`);
    const conversation = await Conversation.findById(conversationId);
    
    if (!conversation) {
      console.log(`[ADMIN] Диалог с ID ${conversationId} не найден в базе данных`);
      return res.status(404).json({ message: 'Диалог не найден' });
    }
    
    console.log(`[ADMIN] Диалог найден, участники: ${conversation.participants}`);
    
    // Получаем сообщения с пагинацией
    const messages = await Message.find({ conversationId })
      .populate('sender', 'name email')
      .skip(skip)
      .limit(parseInt(limit))
      .sort({ createdAt: -1 });
    
    console.log(`[ADMIN] Найдено сообщений: ${messages.length}`);
    
    // Получаем общее количество сообщений для пагинации
    const total = await Message.countDocuments({ conversationId });
    
    res.json({
      messages,
      conversation: {
        id: conversation._id,
        participants: conversation.participants
      },
      pagination: {
        page: parseInt(page),
        limit: parseInt(limit),
        total,
        pages: Math.ceil(total / limit)
      }
    });
  } catch (error) {
    console.error('[ADMIN] Ошибка при получении сообщений диалога:', error);
    res.status(500).json({ message: 'Ошибка сервера при получении сообщений диалога' });
  }
};

/**
 * @desc    Получить диалог по ID
 * @route   GET /api/admin/conversations/:id
 * @access  Admin
 */
const getConversationById = async (req, res) => {
  try {
    const conversationId = req.params.id;
    console.log(`[ADMIN] Запрос диалога с ID: ${conversationId}`);
    
    if (!mongoose.Types.ObjectId.isValid(conversationId)) {
      console.log(`[ADMIN] Недопустимый формат ID диалога: ${conversationId}`);
      return res.status(400).json({ message: 'Недопустимый формат ID диалога' });
    }
    
    // Получаем диалог с данными участников
    const conversation = await Conversation.findById(conversationId)
      .populate('participants', 'name email photos')
      .populate('lastMessage');
    
    if (!conversation) {
      console.log(`[ADMIN] Диалог с ID ${conversationId} не найден в базе данных`);
      return res.status(404).json({ message: 'Диалог не найден' });
    }
    
    console.log(`[ADMIN] Диалог найден, возвращаем данные`);
    res.json(conversation);
  } catch (error) {
    console.error('[ADMIN] Ошибка при получении диалога:', error);
    res.status(500).json({ message: 'Ошибка сервера при получении диалога' });
  }
};

module.exports = {
  getAllUsers,
  getUserDetails,
  toggleUserActive,
  getAppStatistics,
  getAllConversations,
  getConversationById,
  getConversationMessages
};