/**
 * Copyright (c) 2024-2026 Тарабанов Александр Викторович
 * All rights reserved.
 * 
 * This software is proprietary and confidential.
 * Unauthorized copying, modification, or distribution is prohibited.
 * 
 * For licensing inquiries: info@hb3-accelerator.com
 * Website: https://hb3-accelerator.com
 * GitHub: https://github.com/VC-HB3-Accelerator
 */

const express = require('express');
const router = express.Router();
const db = require('../db');
const logger = require('../utils/logger');
const { broadcastMessagesUpdate } = require('../wsHub');
const botManager = require('../services/botManager');
const universalGuestService = require('../services/UniversalGuestService');
const { isUserBlocked } = require('../utils/userUtils');
const { requireAuth } = require('../middleware/auth');
const { requirePermission } = require('../middleware/permissions');
// НОВАЯ СИСТЕМА РОЛЕЙ: используем shared/permissions.js
const { hasPermission, ROLES, PERMISSIONS } = require('/app/shared/permissions');

// GET /api/messages/public?userId=123 - получить публичные сообщения пользователя
router.get('/public', requireAuth, async (req, res) => {
  const userId = req.query.userId;
  const currentUserId = req.user.id;
  
  // Параметры пагинации
  const limit = parseInt(req.query.limit, 10) || 30;
  const offset = parseInt(req.query.offset, 10) || 0;
  const countOnly = req.query.count_only === 'true';

  // Получаем ключ шифрования
  const encryptionUtils = require('../utils/encryptionUtils');
  const encryptionKey = encryptionUtils.getEncryptionKey();

  const parseMetadata = (rawMetadata) => {
    if (!rawMetadata) {
      return {};
    }

    if (typeof rawMetadata === 'object') {
      return rawMetadata;
    }

    try {
      return JSON.parse(rawMetadata);
    } catch (error) {
      logger.warn('[messages/public] Не удалось распарсить metadata гостевого сообщения:', error?.message);
      return {};
    }
  };

  try {
    // Публичные сообщения видны на главной странице пользователя
    const targetUserId = userId || currentUserId;
    const isGuestContact = typeof targetUserId === 'string' && targetUserId.startsWith('guest_');

    if (isGuestContact) {
      const guestId = parseInt(targetUserId.replace('guest_', ''), 10);

      if (Number.isNaN(guestId)) {
        return res.status(400).json({ error: 'Invalid guest ID format' });
      }

      const guestIdentifierResult = await db.getQuery()(
        `WITH decrypted_guest AS (
           SELECT 
             id,
             decrypt_text(identifier_encrypted, $2) AS guest_identifier,
             channel
           FROM unified_guest_messages
           WHERE user_id IS NULL
         )
         SELECT guest_identifier, channel
         FROM decrypted_guest
         GROUP BY guest_identifier, channel
         HAVING MIN(id) = $1
         LIMIT 1`,
        [guestId, encryptionKey]
      );

      if (guestIdentifierResult.rows.length === 0) {
        return res.json({
          success: true,
          messages: [],
          total: 0,
          limit,
          offset,
          hasMore: false
        });
      }

      const guestIdentifier = guestIdentifierResult.rows[0].guest_identifier;
      const guestChannel = guestIdentifierResult.rows[0].channel;

      if (countOnly) {
        const countResult = await db.getQuery()(
          `SELECT COUNT(*) 
             FROM unified_guest_messages 
             WHERE decrypt_text(identifier_encrypted, $2) = $1`,
          [guestIdentifier, encryptionKey]
        );
        const totalCount = parseInt(countResult.rows[0].count, 10);
        return res.json({ success: true, count: totalCount, total: totalCount });
      }

      const messagesResult = await db.getQuery()(
        `SELECT 
           id,
           decrypt_text(content_encrypted, $3) AS content,
           is_ai,
           metadata,
           channel,
           created_at,
           decrypt_text(attachment_filename_encrypted, $3) AS attachment_filename,
           decrypt_text(attachment_mimetype_encrypted, $3) AS attachment_mimetype,
           attachment_size
         FROM unified_guest_messages
         WHERE decrypt_text(identifier_encrypted, $3) = $1
         ORDER BY created_at DESC
         LIMIT $2 OFFSET $4`,
        [guestIdentifier, limit, encryptionKey, offset]
      );

      const countResult = await db.getQuery()(
        `SELECT COUNT(*) 
           FROM unified_guest_messages 
           WHERE decrypt_text(identifier_encrypted, $2) = $1`,
        [guestIdentifier, encryptionKey]
      );
      const totalCount = parseInt(countResult.rows[0].count, 10);

      const mappedMessages = messagesResult.rows.map((row) => {
        const metadata = parseMetadata(row.metadata);
        const baseMessage = {
          id: row.id,
          user_id: targetUserId,
          sender_id: row.is_ai ? null : targetUserId,
          sender_type: row.is_ai ? 'assistant' : 'user',
          content: row.content,
          channel: row.channel || guestChannel,
          role: row.is_ai ? 'assistant' : 'user',
          direction: row.is_ai ? 'out' : 'in',
          created_at: row.created_at,
          message_type: 'public',
          is_ai: row.is_ai,
          metadata,
          last_read_at: null
        };

        if (row.attachment_filename || row.attachment_mimetype || row.attachment_size) {
          baseMessage.attachments = [
            {
              filename: row.attachment_filename,
              mimetype: row.attachment_mimetype,
              size: row.attachment_size
            }
          ];
        }

        if (metadata.consentRequired !== undefined) {
          baseMessage.consentRequired = metadata.consentRequired;
        }
        if (metadata.consentDocuments) {
          baseMessage.consentDocuments = metadata.consentDocuments;
        }
        if (metadata.autoConsentOnReply !== undefined) {
          baseMessage.autoConsentOnReply = metadata.autoConsentOnReply;
        }
        if (metadata.telegramBotUrl) {
          baseMessage.telegramBotUrl = metadata.telegramBotUrl;
        }
        if (metadata.supportEmail) {
          baseMessage.supportEmail = metadata.supportEmail;
        }

        return baseMessage;
      });

      const orderedMessages = mappedMessages.sort((a, b) => new Date(a.created_at) - new Date(b.created_at));

      return res.json({
        success: true,
        messages: orderedMessages,
        total: totalCount,
        limit,
        offset,
        hasMore: offset + limit < totalCount,
        guest: {
          identifier: guestIdentifier,
          channel: guestChannel
        }
      });
    }

    // Если нужен только подсчет
    if (countOnly) {
      const countResult = await db.getQuery()(
        `SELECT COUNT(*) FROM messages 
         WHERE (
           (message_type = 'public' AND ((user_id = $1 AND sender_id = $2) OR (user_id = $2 AND sender_id = $1)))
           OR (message_type = 'user_chat' AND user_id = $1)
         )`,
        [targetUserId, currentUserId]
      );
      const totalCount = parseInt(countResult.rows[0].count, 10);
      return res.json({ success: true, count: totalCount, total: totalCount });
    }
    
    // Загружаем публичные сообщения между пользователями И личные сообщения с ИИ целевого пользователя
    const result = await db.getQuery()(
      `SELECT m.id, m.user_id, m.sender_id, decrypt_text(m.sender_type_encrypted, $2) as sender_type, 
              decrypt_text(m.content_encrypted, $2) as content, 
              decrypt_text(m.channel_encrypted, $2) as channel, 
              decrypt_text(m.role_encrypted, $2) as role, 
              decrypt_text(m.direction_encrypted, $2) as direction, 
              m.created_at, m.message_type,
              arm.last_read_at
       FROM messages m
       LEFT JOIN admin_read_messages arm ON arm.user_id = m.user_id AND arm.admin_id = $5
       WHERE (
         (m.message_type = 'public' AND ((m.user_id = $1 AND m.sender_id = $5) OR (m.user_id = $5 AND m.sender_id = $1)))
         OR (m.message_type = 'user_chat' AND m.user_id = $1)
       )
       ORDER BY m.created_at ASC
       LIMIT $3 OFFSET $4`,
      [targetUserId, encryptionKey, limit, offset, currentUserId]
    );
    
    // Получаем общее количество для пагинации
    const countResult = await db.getQuery()(
      `SELECT COUNT(*) FROM messages 
       WHERE (
         (message_type = 'public' AND ((user_id = $1 AND sender_id = $2) OR (user_id = $2 AND sender_id = $1)))
         OR (message_type = 'user_chat' AND user_id = $1)
       )`,
      [targetUserId, currentUserId]
    );
    const totalCount = parseInt(countResult.rows[0].count, 10);
    
    res.json({
      success: true,
      messages: result.rows,
      total: totalCount,
      limit,
      offset,
      hasMore: offset + limit < totalCount
    });
  } catch (e) {
    res.status(500).json({ error: 'DB error', details: e.message });
  }
});

// GET /api/messages/private - получить приватные сообщения текущего пользователя
router.get('/private', requireAuth, async (req, res) => {
  const currentUserId = req.user.id;
  
  // Параметры пагинации
  const limit = parseInt(req.query.limit, 10) || 30;
  const offset = parseInt(req.query.offset, 10) || 0;
  const countOnly = req.query.count_only === 'true';

  // Получаем ключ шифрования
  const encryptionUtils = require('../utils/encryptionUtils');
  const encryptionKey = encryptionUtils.getEncryptionKey();

  try {
    // Если нужен только подсчет
    if (countOnly) {
      const countResult = await db.getQuery()(
        `SELECT COUNT(*) FROM messages WHERE user_id = $1 AND message_type = 'admin_chat'`,
        [currentUserId]
      );
      const totalCount = parseInt(countResult.rows[0].count, 10);
      return res.json({ success: true, count: totalCount, total: totalCount });
    }
    
    // Приватные сообщения видны только в личных сообщениях
    const result = await db.getQuery()(
      `SELECT m.id, m.user_id, decrypt_text(m.sender_type_encrypted, $2) as sender_type, 
              decrypt_text(m.content_encrypted, $2) as content, 
              decrypt_text(m.channel_encrypted, $2) as channel, 
              decrypt_text(m.role_encrypted, $2) as role, 
              decrypt_text(m.direction_encrypted, $2) as direction, 
              m.created_at, m.message_type,
              arm.last_read_at
       FROM messages m
       LEFT JOIN admin_read_messages arm ON arm.user_id = m.user_id AND arm.admin_id = $5
       WHERE m.user_id = $1 AND m.message_type = 'admin_chat'
       ORDER BY m.created_at DESC
       LIMIT $3 OFFSET $4`,
      [currentUserId, encryptionKey, limit, offset, currentUserId]
    );
    
    // Получаем общее количество для пагинации
      const countResult = await db.getQuery()(
        `SELECT COUNT(*) FROM messages WHERE user_id = $1 AND message_type = 'admin_chat'`,
        [currentUserId]
      );
    const totalCount = parseInt(countResult.rows[0].count, 10);
    
    res.json({
      success: true,
      messages: result.rows,
      total: totalCount,
      limit,
      offset,
      hasMore: offset + limit < totalCount
    });
  } catch (e) {
    res.status(500).json({ error: 'DB error', details: e.message });
  }
});



// УДАЛЕНО: GET /api/messages - УСТАРЕВШИЙ эндпоинт (используйте /api/messages/public или /api/messages/private)
// УДАЛЕНО: POST /api/messages - УСТАРЕВШИЙ эндпоинт (используйте /api/messages/send или /api/chat/message)

// POST /api/messages/mark-read
router.post('/mark-read', async (req, res) => {
  try {
    // console.log('[DEBUG] /mark-read req.user:', req.user);
    // console.log('[DEBUG] /mark-read req.body:', req.body);
    // НОВАЯ СИСТЕМА РОЛЕЙ: определяем adminId через новую систему
    let adminId = req.user?.id;
    
    // Если нет авторизованного пользователя, используем fallback
    if (!adminId) {
      const result = await db.query('SELECT id FROM users LIMIT 1');
      adminId = result.rows[0]?.id || 1;
    }
    
    const { userId, lastReadAt } = req.body;
    if (!userId || !lastReadAt) {
      // console.error('[ERROR] /mark-read: userId or lastReadAt missing');
      return res.status(400).json({ error: 'userId and lastReadAt required' });
    }
    await db.query(`
      INSERT INTO admin_read_messages (admin_id, user_id, last_read_at)
      VALUES ($1, $2, $3)
      ON CONFLICT (admin_id, user_id) DO UPDATE SET last_read_at = EXCLUDED.last_read_at
    `, [adminId, userId, lastReadAt]);
    res.json({ success: true });
  } catch (e) {
    // console.error('[ERROR] /mark-read:', e);
    res.status(500).json({ error: e.message });
  }
});

// GET /api/messages/read-status
router.get('/read-status', async (req, res) => {
  try {
    // console.log('[DEBUG] /read-status req.user:', req.user);
    // console.log('[DEBUG] /read-status req.session:', req.session);
    // console.log('[DEBUG] /read-status req.session.userId:', req.session && req.session.userId);
    // НОВАЯ СИСТЕМА РОЛЕЙ: определяем adminId через новую систему
    let adminId = req.user?.id;
    
    // Если нет авторизованного пользователя, используем fallback
    if (!adminId) {
      const result = await db.query('SELECT id FROM users LIMIT 1');
      adminId = result.rows[0]?.id || 1;
    }
    const result = await db.query('SELECT user_id, last_read_at FROM admin_read_messages WHERE admin_id = $1', [adminId]);
    // console.log('[DEBUG] /read-status SQL result:', result.rows);
    const map = {};
    for (const row of result.rows) {
      map[row.user_id] = row.last_read_at;
    }
    res.json(map);
  } catch (e) {
    // console.error('[ERROR] /read-status:', e);
    res.status(500).json({ error: e.message });
  }
});

// УДАЛЕНО: Дублирующиеся endpoint'ы перенесены ниже

// Массовая рассылка сообщения во все каналы пользователя
// Массовая рассылка сообщений
router.post('/broadcast', requireAuth, requirePermission(PERMISSIONS.BROADCAST), async (req, res) => {
  const { user_id, content } = req.body;
  if (!user_id || !content) {
    return res.status(400).json({ error: 'user_id и content обязательны' });
  }

  // ✨ Проверка прав через adminLogicService (только editor может делать рассылку!)
  const encryptedDb = require('../services/encryptedDatabaseService');
  const users = await encryptedDb.getData('users', { id: req.session.userId }, 1);
  const userRole = users && users.length > 0 ? users[0].role : 'user';
  
  const adminLogicService = require('../services/adminLogicService');
  const canBroadcast = adminLogicService.canPerformAdminAction({
    role: userRole,  // Передаем точную роль ('editor', 'readonly', 'user')
    action: 'broadcast_message'
  });

  if (!canBroadcast) {
    console.warn(`[Messages] Пользователь ${req.session.userId} (роль: ${userRole}) пытался сделать broadcast без прав`);
    return res.status(403).json({ 
      error: 'Только редакторы (editor) могут делать массовую рассылку' 
    });
  }

  // Получаем ключ шифрования через унифицированную утилиту
  const encryptionUtils = require('../utils/encryptionUtils');
  const encryptionKey = encryptionUtils.getEncryptionKey();

  try {
    // Получаем все идентификаторы пользователя
    const identitiesRes = await db.getQuery()(
      'SELECT decrypt_text(provider_encrypted, $2) as provider, decrypt_text(provider_id_encrypted, $2) as provider_id FROM user_identities WHERE user_id = $1',
      [user_id, encryptionKey]
    );
    const identities = identitiesRes.rows;
    // --- Найти или создать беседу (conversation) ---
    let conversationResult = await db.getQuery()(
      'SELECT id, user_id, created_at, updated_at, title FROM conversations WHERE user_id = $1 ORDER BY updated_at DESC, created_at DESC LIMIT 1',
      [user_id, encryptionKey]
    );
    let conversation;
    if (conversationResult.rows.length === 0) {
      const title = `Чат с пользователем ${user_id}`;
      const newConv = await db.getQuery()(
        'INSERT INTO conversations (user_id, title, created_at, updated_at) VALUES ($1, $2, NOW(), NOW()) RETURNING *',
        [user_id, title]
      );
      conversation = newConv.rows[0];
    } else {
      conversation = conversationResult.rows[0];
    }
    const results = [];
    let sent = false;
    // Email
    const email = identities.find(i => i.provider === 'email')?.provider_id;
    if (email) {
      try {
        const emailBot = botManager.getBot('email');
        if (emailBot && emailBot.isInitialized) {
          await emailBot.sendEmail(email, 'Новое сообщение', content);
          // Сохраняем в messages с conversation_id
          await db.getQuery()(
            `INSERT INTO messages (conversation_id, sender_id, sender_type_encrypted, content_encrypted, channel_encrypted, role_encrypted, direction_encrypted, message_type, user_id, role, direction, created_at)
             VALUES ($1, $2, encrypt_text($3, $12), encrypt_text($4, $12), encrypt_text($5, $12), encrypt_text($6, $12), encrypt_text($7, $12), $8, $9, $10, $11, NOW())`,
            [conversation.id, req.session.userId, 'editor', content, 'email', 'user', 'out', 'user_chat', user_id, 'user', 'out', encryptionKey]
          );
          results.push({ channel: 'email', status: 'sent' });
          sent = true;
        } else {
          console.warn('[messages.js] Email Bot не инициализирован');
          results.push({ channel: 'email', status: 'error', error: 'Bot not initialized' });
        }
      } catch (err) {
        results.push({ channel: 'email', status: 'error', error: err.message });
      }
    }
    // Telegram
    const telegram = identities.find(i => i.provider === 'telegram')?.provider_id;
    if (telegram) {
      try {
        const telegramBot = botManager.getBot('telegram');
        if (telegramBot && telegramBot.isInitialized) {
          const bot = telegramBot.getBot();
          await bot.telegram.sendMessage(telegram, content);
          await db.getQuery()(
            `INSERT INTO messages (conversation_id, sender_id, sender_type_encrypted, content_encrypted, channel_encrypted, role_encrypted, direction_encrypted, message_type, user_id, role, direction, created_at)
             VALUES ($1, $2, encrypt_text($3, $12), encrypt_text($4, $12), encrypt_text($5, $12), encrypt_text($6, $12), encrypt_text($7, $12), $8, $9, $10, $11, NOW())`,
            [conversation.id, req.session.userId, 'editor', content, 'telegram', 'user', 'out', 'user_chat', user_id, 'user', 'out', encryptionKey]
          );
          results.push({ channel: 'telegram', status: 'sent' });
          sent = true;
        } else {
          console.warn('[messages.js] Telegram Bot не инициализирован');
          results.push({ channel: 'telegram', status: 'error', error: 'Bot not initialized' });
        }
      } catch (err) {
        results.push({ channel: 'telegram', status: 'error', error: err.message });
      }
    }
    // Wallet/web3
    const wallet = identities.find(i => i.provider === 'wallet')?.provider_id;
    if (wallet) {
      // Здесь можно реализовать отправку через web3, если нужно
      await db.getQuery()(
        `INSERT INTO messages (conversation_id, sender_id, sender_type_encrypted, content_encrypted, channel_encrypted, role_encrypted, direction_encrypted, message_type, user_id, role, direction, created_at)
         VALUES ($1, $2, encrypt_text($3, $12), encrypt_text($4, $12), encrypt_text($5, $12), encrypt_text($6, $12), encrypt_text($7, $12), $8, $9, $10, $11, NOW())`,
        [conversation.id, req.session.userId, 'editor', content, 'wallet', 'user', 'out', 'user_chat', user_id, 'user', 'out', encryptionKey]
      );
      results.push({ channel: 'wallet', status: 'saved' });
      sent = true;
    }
    if (!sent) {
      return res.status(400).json({ error: 'У пользователя нет ни одного канала для рассылки.' });
    }
    res.json({ success: true, results });
  } catch (e) {
    res.status(500).json({ error: 'Broadcast error', details: e.message });
  }
});

// POST /api/messages/send - новый эндпоинт для отправки сообщений с проверкой ролей
router.post('/send', requireAuth, async (req, res) => {
  const { recipientId, content, messageType = 'public', markAsRead = false } = req.body;
  
  if (!recipientId || !content) {
    return res.status(400).json({ error: 'recipientId и content обязательны' });
  }
  
  if (!['public', 'private'].includes(messageType)) {
    return res.status(400).json({ error: 'messageType должен быть "public" или "private"' });
  }

  const senderId = req.user.id;
  const senderRole = req.user.role || req.user.userAccessLevel?.level || 'user';
  const isGuestRecipient = typeof recipientId === 'string' && recipientId.startsWith('guest_');

  try {
    if (isGuestRecipient) {
      if (!hasPermission(senderRole, PERMISSIONS.SEND_TO_USERS)) {
        return res.status(403).json({ error: 'Недостаточно прав для отправки сообщений гостям' });
      }

      if (messageType !== 'public') {
        return res.status(400).json({ error: 'Гостям можно отправлять только публичные сообщения' });
      }

      const guestInternalId = parseInt(recipientId.replace('guest_', ''), 10);
      if (Number.isNaN(guestInternalId)) {
        return res.status(400).json({ error: 'Некорректный формат гостевого идентификатора' });
      }

      const encryptionUtils = require('../utils/encryptionUtils');
      const encryptionKey = encryptionUtils.getEncryptionKey();

      const guestIdentifierResult = await db.getQuery()(
        `WITH decrypted_guest AS (
           SELECT 
             id,
             decrypt_text(identifier_encrypted, $2) AS guest_identifier,
             channel
           FROM unified_guest_messages
           WHERE user_id IS NULL
         )
         SELECT guest_identifier, channel
         FROM decrypted_guest
         GROUP BY guest_identifier, channel
         HAVING MIN(id) = $1
         LIMIT 1`,
        [guestInternalId, encryptionKey]
      );

      if (guestIdentifierResult.rows.length === 0) {
        return res.status(404).json({ error: 'Гостевой контакт не найден' });
      }

      const guestIdentifier = guestIdentifierResult.rows[0].guest_identifier;
      const guestChannel = guestIdentifierResult.rows[0].channel;
      const deliveryMeta = {
        sentBy: 'admin_panel',
        senderId,
        senderRole,
        originalRecipientId: recipientId,
        messageType
      };

      let deliveryStatus = { success: true };

      try {
        if (guestChannel === 'telegram') {
          const telegramBot = botManager.getBot('telegram');
          if (telegramBot && telegramBot.isInitialized) {
            await telegramBot.getBot().telegram.sendMessage(guestIdentifier, content);
          } else {
            logger.warn('[messages/send] Telegram Bot не инициализирован, сообщение сохранено только в истории');
            deliveryStatus = { success: false, error: 'Telegram bot inactive' };
          }
        } else if (guestChannel === 'email') {
          const emailBot = botManager.getBot('email');
          if (emailBot && emailBot.isInitialized) {
            await emailBot.sendEmail(guestIdentifier, 'Ответ от администратора', content);
          } else {
            logger.warn('[messages/send] Email Bot не инициализирован, сообщение сохранено только в истории');
            deliveryStatus = { success: false, error: 'Email bot inactive' };
          }
        } else {
          logger.info(`[messages/send] Гость ${guestIdentifier} имеет канал ${guestChannel}, внешняя доставка не требуется`);
        }
      } catch (deliveryError) {
        logger.error('[messages/send] Ошибка отправки гостю через внешний канал:', deliveryError);
        deliveryStatus = { success: false, error: deliveryError.message };
      }

      const saveResult = await universalGuestService.saveAiResponse({
        identifier: guestIdentifier,
        channel: guestChannel,
        content,
        metadata: deliveryMeta
      });

      broadcastMessagesUpdate();

      return res.json({
        success: true,
        message: {
          id: saveResult.messageId,
          user_id: recipientId,
          sender_id: null,
          sender_type: 'assistant',
          content,
          channel: guestChannel,
          role: 'assistant',
          direction: 'out',
          created_at: saveResult.created_at,
          message_type: 'public',
          metadata: deliveryMeta
        },
        delivery: deliveryStatus
      });
    }

    // Работа с зарегистрированными пользователями
    let recipientIdNum;
    if (messageType === 'private') {
      recipientIdNum = 1;
    } else {
      recipientIdNum = parseInt(recipientId, 10);
      if (Number.isNaN(recipientIdNum)) {
        return res.status(400).json({ error: 'recipientId должен быть числом' });
      }
    }

    console.log('[DEBUG] /messages/send: senderId:', senderId, 'senderRole:', senderRole);

    const recipientResult = await db.getQuery()(
      'SELECT id, role FROM users WHERE id = $1',
      [recipientIdNum]
    );

    if (recipientResult.rows.length === 0) {
      return res.status(404).json({ error: 'Получатель не найден' });
    }

    const recipientRole = recipientResult.rows[0].role;
    console.log('[DEBUG] /messages/send: recipientId:', recipientIdNum, 'recipientRole:', recipientRole);

    const { canSendMessage } = require('/app/shared/permissions');
    const permissionCheck = canSendMessage(senderRole, recipientRole, senderId, recipientIdNum);

    console.log('[DEBUG] /messages/send: canSend:', permissionCheck.canSend, 'senderRole:', senderRole, 'recipientRole:', recipientRole, 'error:', permissionCheck.errorMessage);

    if (!permissionCheck.canSend) {
      return res.status(403).json({
        error: permissionCheck.errorMessage || 'Недостаточно прав для отправки сообщения этому получателю'
      });
    }

    const unifiedMessageProcessor = require('../services/unifiedMessageProcessor');
    const identityService = require('../services/identity-service');

    const walletIdentity = await identityService.findIdentity(senderId, 'wallet');
    if (!walletIdentity) {
      return res.status(403).json({
        error: 'Требуется подключение кошелька'
      });
    }

    const identifier = `wallet:${walletIdentity.provider_id}`;

    const result = await unifiedMessageProcessor.processMessage({
      identifier,
      content,
      channel: 'web',
      attachments: [],
      conversationId: null,
      recipientId: recipientIdNum,
      userId: senderId,
      metadata: {
        messageType,
        markAsRead
      }
    });

    // Отправляем сообщение через Telegram/Email, если у получателя есть эти идентификаторы
    try {
      const encryptionUtils = require('../utils/encryptionUtils');
      const encryptionKey = encryptionUtils.getEncryptionKey();
      const botManager = require('../services/botManager');
      const FRONTEND_URL = process.env.FRONTEND_URL || 'https://xn--80aqc0am6d.xn--p1ai';
      
      // Получаем все идентификаторы получателя
      const identitiesRes = await db.getQuery()(
        'SELECT decrypt_text(provider_encrypted, $2) as provider, decrypt_text(provider_id_encrypted, $2) as provider_id FROM user_identities WHERE user_id = $1',
        [recipientIdNum, encryptionKey]
      );
      const identities = identitiesRes.rows;
      
      // Функция для добавления параметров к ссылкам на страницы контента
      // Редактор копирует URL из адресной строки и отправляет его в чат
      // Функция находит все ссылки на /content/page/ или /public/page/ и добавляет параметры авторизации
      // Best practice: используем встроенный URL API для надежной обработки
      const addAuthParamsToLinks = (text, telegramId, email) => {
        if (!text) return text;
        
        const params = {};
        if (telegramId) {
          params.telegramId = telegramId;
        }
        if (email) {
          params.email = email;
        }
        
        if (Object.keys(params).length === 0) return text;
        
        // Вспомогательная функция для добавления параметров к URL
        const addParamsToUrl = (urlString, baseUrl = null) => {
          try {
            // Парсим URL (полный или относительный)
            const url = baseUrl ? new URL(urlString, baseUrl) : new URL(urlString);
            
            // Проверяем, является ли это страницей контента
            const pathname = url.pathname;
            if (!pathname.match(/^\/content\/page\/\d+$/) && !pathname.match(/^\/public\/page\/\d+$/)) {
              return urlString; // Не страница контента, возвращаем как есть
            }
            
            // Проверяем, не добавлены ли уже параметры авторизации
            if (url.searchParams.has('telegramId') || url.searchParams.has('email')) {
              return urlString; // Параметры уже есть
            }
            
            // Добавляем параметры
            Object.entries(params).forEach(([key, value]) => {
              url.searchParams.set(key, value);
            });
            
            return url.toString();
          } catch (error) {
            // Если URL некорректный, возвращаем как есть
            return urlString;
          }
        };
        
        // Обрабатываем HTML-ссылки <a href="...">
        text = text.replace(/<a\s+([^>]*?)href=["']([^"']*)["']([^>]*)>/gi, (match, beforeAttrs, url, afterAttrs) => {
          if (!url) return match;
          
          const newUrl = addParamsToUrl(url, FRONTEND_URL);
          if (newUrl === url) return match; // URL не изменился
          
          return `<a ${beforeAttrs || ''}href="${newUrl}"${afterAttrs || ''}>`;
        });
        
        // Обрабатываем обычные текстовые ссылки (URL из адресной строки браузера)
        // Ищем все варианты: полные URL и относительные пути
        // Используем два отдельных паттерна для надежности
        
        // Паттерн для полных URL: https://domain.com/content/page/38
        const fullUrlPattern = /https?:\/\/[^\s<>"']+?(?:\/content\/page\/\d+|\/public\/page\/\d+)[^\s<>"']*/gi;
        
        text = text.replace(fullUrlPattern, (match, offset) => {
          // Проверяем, не находимся ли мы внутри HTML-тега
          const beforeMatch = text.substring(0, offset);
          const lastOpenTag = beforeMatch.lastIndexOf('<a');
          const lastCloseTag = beforeMatch.lastIndexOf('</a>');
          
          if (lastOpenTag > lastCloseTag) {
            // Мы внутри открытого тега <a>, пропускаем
            return match;
          }
          
          // Обрабатываем URL
          const newUrl = addParamsToUrl(match);
          return newUrl === match ? match : newUrl;
        });
        
        // Паттерн для относительных путей: /content/page/38
        const relativePathPattern = /\/content\/page\/\d+[^\s<>"']*|\/public\/page\/\d+[^\s<>"']*/g;
        
        text = text.replace(relativePathPattern, (match, offset) => {
          // Пропускаем, если это уже полный URL (начинается с http)
          if (offset > 0 && text.substring(Math.max(0, offset - 7), offset).match(/https?:\/\//i)) {
            return match;
          }
          
          // Проверяем, не находимся ли мы внутри HTML-тега
          const beforeMatch = text.substring(0, offset);
          const lastOpenTag = beforeMatch.lastIndexOf('<a');
          const lastCloseTag = beforeMatch.lastIndexOf('</a>');
          
          if (lastOpenTag > lastCloseTag) {
            // Мы внутри открытого тега <a>, пропускаем
            return match;
          }
          
          // Обрабатываем относительный путь
          const newUrl = addParamsToUrl(match, FRONTEND_URL);
          return newUrl === match ? match : newUrl;
        });
        
        return text;
      };
      
      // Отправка через Telegram
      const telegramIdentity = identities.find(i => i.provider === 'telegram');
      if (telegramIdentity && telegramIdentity.provider_id) {
        try {
          const telegramBot = botManager.getBot('telegram');
          if (telegramBot && telegramBot.isInitialized) {
            // Добавляем параметры к ссылкам для автоматической авторизации
            const contentWithLinks = addAuthParamsToLinks(content, telegramIdentity.provider_id, null);
            await telegramBot.getBot().telegram.sendMessage(telegramIdentity.provider_id, contentWithLinks);
            logger.info(`[messages/send] Сообщение отправлено через Telegram пользователю ${recipientIdNum}`);
          } else {
            logger.warn('[messages/send] Telegram Bot не инициализирован, сообщение сохранено только в истории');
          }
        } catch (telegramError) {
          logger.error('[messages/send] Ошибка отправки через Telegram:', telegramError);
        }
      }
      
      // Отправка через Email
      const emailIdentity = identities.find(i => i.provider === 'email');
      if (emailIdentity && emailIdentity.provider_id) {
        try {
          const emailBot = botManager.getBot('email');
          if (emailBot && emailBot.isInitialized) {
            // Добавляем параметры к ссылкам для автоматической авторизации
            const contentWithLinks = addAuthParamsToLinks(content, null, emailIdentity.provider_id);
            
            // Проверяем, содержит ли контент HTML-теги
            const isHtml = /<[a-z][\s\S]*>/i.test(contentWithLinks);
            
            if (isHtml) {
              // Если контент содержит HTML, отправляем как HTML с текстовой версией
              // Создаем текстовую версию (удаляем HTML-теги для простоты)
              const textVersion = contentWithLinks.replace(/<[^>]*>/g, '').replace(/\s+/g, ' ').trim();
              await emailBot.sendEmailWithHtml(emailIdentity.provider_id, 'Новое сообщение', textVersion, contentWithLinks);
            } else {
              // Если контент текстовый, отправляем как текст
              await emailBot.sendEmail(emailIdentity.provider_id, 'Новое сообщение', contentWithLinks);
            }
            logger.info(`[messages/send] Сообщение отправлено через Email пользователю ${recipientIdNum}`);
          } else {
            logger.warn('[messages/send] Email Bot не инициализирован, сообщение сохранено только в истории');
          }
        } catch (emailError) {
          logger.error('[messages/send] Ошибка отправки через Email:', emailError);
        }
      }
    } catch (deliveryError) {
      // Не критично, если не удалось отправить через внешние каналы - сообщение уже сохранено в БД
      logger.warn('[messages/send] Ошибка отправки через внешние каналы (не критично):', deliveryError);
    }

    if (markAsRead) {
      try {
        const lastReadAt = new Date().toISOString();
        await db.getQuery()(
          `INSERT INTO admin_read_messages (admin_id, user_id, last_read_at)
           VALUES ($1, $2, $3)
           ON CONFLICT (admin_id, user_id) DO UPDATE SET last_read_at = EXCLUDED.last_read_at`,
          [senderId, recipientIdNum, lastReadAt]
        );
      } catch (markError) {
        console.warn('[WARNING] /send mark-read error:', markError);
      }
    }

    res.json({ success: true, message: result });
  } catch (e) {
    console.error('[ERROR] /send:', e);
    res.status(500).json({ error: 'DB error', details: e.message });
  }
});

// POST /api/messages/private/send - отправка приватного сообщения
router.post('/private/send', requireAuth, async (req, res) => {
  const { recipientId, content } = req.body;
  const senderId = req.user.id;
  
  if (!recipientId || !content) {
    return res.status(400).json({ error: 'recipientId и content обязательны' });
  }
  
  try {
    const senderRole = req.user.role || req.user.userAccessLevel?.level || 'user';
    
    // Получаем информацию о получателе
    const recipientResult = await db.getQuery()(
      'SELECT id, role FROM users WHERE id = $1',
      [recipientId]
    );
    
    if (recipientResult.rows.length === 0) {
      return res.status(404).json({ error: 'Получатель не найден' });
    }
    
    const recipientRole = recipientResult.rows[0].role;
    
    // Используем централизованную проверку прав
    const { canSendMessage } = require('/app/shared/permissions');
    const permissionCheck = canSendMessage(senderRole, recipientRole, senderId, recipientId);
    
    if (!permissionCheck.canSend) {
      return res.status(403).json({ 
        error: permissionCheck.errorMessage || 'Недостаточно прав для отправки приватного сообщения' 
      });
    }
    
    // ✨ Используем unifiedMessageProcessor для унификации
    const unifiedMessageProcessor = require('../services/unifiedMessageProcessor');
    const identityService = require('../services/identity-service');
    
    // Получаем wallet идентификатор отправителя
    const walletIdentity = await identityService.findIdentity(senderId, 'wallet');
    if (!walletIdentity) {
      return res.status(403).json({
        error: 'Требуется подключение кошелька'
      });
    }
    
    const identifier = `wallet:${walletIdentity.provider_id}`;
    
    // Обрабатываем через unifiedMessageProcessor
    // Для приватных сообщений recipientId всегда = 1 (редактор)
    const result = await unifiedMessageProcessor.processMessage({
      identifier: identifier,
      content: content,
      channel: 'web',
      attachments: [],
      conversationId: null, // unifiedMessageProcessor сам найдет/создаст беседу
      recipientId: 1, // Приватные сообщения всегда к редактору
      userId: senderId,
      metadata: {}
    });
    
    res.json({ 
      success: true, 
      message: result
    });
    
  } catch (error) {
    console.error('[ERROR] /messages/private/send:', error);
    res.status(500).json({ error: 'DB error', details: error.message });
  }
});

// GET /api/messages/private/conversations - получить приватные чаты пользователя
router.get('/private/conversations', requireAuth, async (req, res) => {
  const currentUserId = req.user.id;
  console.log('[DEBUG] /messages/private/conversations currentUserId:', currentUserId);
  
  try {
    const encryptionUtils = require('../utils/encryptionUtils');
    const encryptionKey = encryptionUtils.getEncryptionKey();
    
    // Получаем приватные чаты где пользователь является участником
    const result = await db.getQuery()(
      `SELECT DISTINCT 
         c.id as conversation_id,
         c.user_id,
         c.title,
         c.updated_at,
         COUNT(m.id) as message_count
       FROM conversations c
       INNER JOIN conversation_participants cp ON c.id = cp.conversation_id
       LEFT JOIN messages m ON c.id = m.conversation_id AND m.message_type = 'admin_chat'
       WHERE cp.user_id = $1 AND c.conversation_type = 'private'
       GROUP BY c.id, c.user_id, c.title, c.updated_at
       ORDER BY c.updated_at DESC`,
      [currentUserId]
    );
    
    console.log('[DEBUG] /messages/private/conversations result:', result.rows);
    
    res.json({
      success: true,
      conversations: result.rows
    });
    
  } catch (error) {
    console.error('[ERROR] /messages/private/conversations:', error);
    res.status(500).json({ error: 'DB error', details: error.message });
  }
});

// GET /api/messages/private/unread-count - получить количество непрочитанных приватных сообщений
router.get('/private/unread-count', requireAuth, async (req, res) => {
  const currentUserId = req.user.id;
  
  try {
    // Подсчитываем непрочитанные приватные сообщения для текущего пользователя
    const result = await db.getQuery()(
      `SELECT COUNT(*) as unread_count
       FROM messages m
       INNER JOIN conversations c ON m.conversation_id = c.id
       INNER JOIN conversation_participants cp ON c.id = cp.conversation_id
       WHERE cp.user_id = $1 
         AND c.conversation_type = 'private'
         AND m.message_type = 'admin_chat'
         AND m.user_id = $1  -- сообщения адресованные текущему пользователю
         AND m.sender_id != $1  -- исключаем собственные сообщения
         AND NOT EXISTS (
           SELECT 1 FROM admin_read_messages arm 
           WHERE arm.admin_id = $1 
             AND arm.user_id = $1
             AND arm.last_read_at >= m.created_at
         )`,
      [currentUserId]
    );
    
    const unreadCount = parseInt(result.rows[0].unread_count) || 0;
    
    res.json({
      success: true,
      unreadCount: unreadCount
    });
    
  } catch (error) {
    console.error('[ERROR] /messages/private/unread-count:', error);
    res.status(500).json({ error: 'DB error', details: error.message });
  }
});

// POST /api/messages/private/mark-read - отметить приватные сообщения как прочитанные
router.post('/private/mark-read', requireAuth, async (req, res) => {
  const { conversationId } = req.body;
  const currentUserId = req.user.id;
  
  if (!conversationId) {
    return res.status(400).json({ error: 'conversationId обязателен' });
  }
  
  try {
    // Проверяем, что пользователь является участником этого чата
    const participantCheck = await db.getQuery()(
      'SELECT 1 FROM conversation_participants WHERE conversation_id = $1 AND user_id = $2',
      [conversationId, currentUserId]
    );
    
    if (participantCheck.rows.length === 0) {
      return res.status(403).json({ error: 'Доступ запрещен' });
    }
    
    // Отмечаем сообщения как прочитанные
    await db.getQuery()(
      `INSERT INTO admin_read_messages (admin_id, user_id, last_read_at)
       VALUES ($1, $1, NOW())
       ON CONFLICT (admin_id, user_id)
       DO UPDATE SET last_read_at = NOW()`,
      [currentUserId]
    );
    
    // Отправляем обновление через WebSocket
    broadcastMessagesUpdate();
    
    res.json({ success: true });
    
  } catch (error) {
    console.error('[ERROR] /messages/private/mark-read:', error);
    res.status(500).json({ error: 'DB error', details: error.message });
  }
});

// GET /api/messages/private/:conversationId - получить историю приватного чата
router.get('/private/:conversationId', requireAuth, async (req, res) => {
  const conversationId = req.params.conversationId;
  const currentUserId = req.user.id;
  
  try {
    // Проверяем, что пользователь является участником этого чата
    const participantCheck = await db.getQuery()(
      'SELECT 1 FROM conversation_participants WHERE conversation_id = $1 AND user_id = $2',
      [conversationId, currentUserId]
    );
    
    if (participantCheck.rows.length === 0) {
      return res.status(403).json({ error: 'Доступ запрещен' });
    }
    
    const encryptionUtils = require('../utils/encryptionUtils');
    const encryptionKey = encryptionUtils.getEncryptionKey();
    
    // Получаем историю сообщений
    const result = await db.getQuery()(
      `SELECT 
         m.id,
         m.sender_id,
         m.user_id,
         decrypt_text(m.sender_type_encrypted, $2) as sender_type,
         decrypt_text(m.content_encrypted, $2) as content,
         decrypt_text(m.channel_encrypted, $2) as channel,
         decrypt_text(m.role_encrypted, $2) as role,
         decrypt_text(m.direction_encrypted, $2) as direction,
         m.message_type,
         m.created_at
       FROM messages m
       WHERE m.conversation_id = $1 AND m.message_type = 'admin_chat'
       ORDER BY m.created_at ASC`,
      [conversationId, encryptionKey]
    );
    
    res.json({
      success: true,
      messages: result.rows
    });
    
  } catch (error) {
    console.error('[ERROR] /messages/private/:conversationId:', error);
    res.status(500).json({ error: 'DB error', details: error.message });
  }
});

// GET /api/messages/conversations?userId=123 - получить диалоги пользователя
router.get('/conversations', requireAuth, async (req, res) => {
  const userId = req.query.userId;
  if (!userId) return res.status(400).json({ error: 'userId required' });
  
  try {
    const result = await db.getQuery()(
      'SELECT * FROM conversations WHERE user_id = $1 ORDER BY updated_at DESC, created_at DESC',
      [userId]
    );
    res.json({ success: true, conversations: result.rows });
  } catch (e) {
    res.status(500).json({ error: 'DB error', details: e.message });
  }
});

// POST /api/messages/conversations - создать диалог для пользователя
router.post('/conversations', requireAuth, async (req, res) => {
  const { userId, title } = req.body;
  if (!userId) return res.status(400).json({ error: 'userId required' });
  
  // Получаем ключ шифрования через унифицированную утилиту
  const encryptionUtils = require('../utils/encryptionUtils');
  const encryptionKey = encryptionUtils.getEncryptionKey();
  
  try {
    const result = await db.getQuery()(
      `INSERT INTO conversations (user_id, title, created_at, updated_at)
       VALUES ($1, $2, NOW(), NOW()) RETURNING *`,
      [userId, title || 'Новый диалог']
    );
    res.json({ success: true, conversation: result.rows[0] });
  } catch (e) {
    res.status(500).json({ error: 'DB error', details: e.message });
  }
});

// DELETE /api/messages/delete-history/:userId - удалить историю сообщений пользователя (новый API)
router.delete('/delete-history/:userId', requireAuth, requirePermission(PERMISSIONS.DELETE_MESSAGES), async (req, res) => {
  const userId = req.params.userId;
  if (!userId) {
    return res.status(400).json({ error: 'userId required' });
  }
  
  try {
    // Проверяем права администратора
    if (!req.user || !req.user.userAccessLevel?.hasAccess) {
      return res.status(403).json({ error: 'Only administrators can delete message history' });
    }
    
    // Удаляем все сообщения пользователя
    const result = await db.getQuery()(
      'DELETE FROM messages WHERE user_id = $1 RETURNING id',
      [userId]
    );
    
    res.json({ 
      success: true, 
      deletedCount: result.rows.length,
      message: `Deleted ${result.rows.length} messages for user ${userId}`
    });
  } catch (e) {
    console.error('[ERROR] /delete-history/:userId:', e);
    res.status(500).json({ error: 'DB error', details: e.message });
  }
});

// DELETE /api/messages/history/:userId - удалить историю сообщений пользователя
// Удаление истории сообщений пользователя
router.delete('/history/:userId', requireAuth, requirePermission(PERMISSIONS.DELETE_MESSAGES), async (req, res) => {
  const userId = req.params.userId;
  if (!userId) {
    return res.status(400).json({ error: 'userId required' });
  }
  
  try {
    // Проверяем права администратора
    if (!req.user || !req.user.userAccessLevel?.hasAccess) {
      return res.status(403).json({ error: 'Only administrators can delete message history' });
    }
    
    // Удаляем все сообщения пользователя
    const result = await db.getQuery()(
      'DELETE FROM messages WHERE user_id = $1 RETURNING id',
      [userId]
    );
    
    // Удаляем хеши дедупликации для этого пользователя
    const dedupResult = await db.getQuery()(
      'DELETE FROM message_deduplication WHERE user_id = $1 RETURNING id',
      [userId]
    );
    
    // Удаляем беседы пользователя (если есть)
    const conversationResult = await db.getQuery()(
      'DELETE FROM conversations WHERE user_id = $1 RETURNING id',
      [userId]
    );
    
    console.log(`[messages.js] Deleted ${result.rowCount} messages, ${dedupResult.rowCount} deduplication hashes, and ${conversationResult.rowCount} conversations for user ${userId}`);
    
    // Отправляем обновление через WebSocket
    broadcastMessagesUpdate();
    
    res.json({ 
      success: true, 
      deletedMessages: result.rowCount,
      deletedConversations: conversationResult.rowCount
    });
  } catch (e) {
    console.error('[ERROR] /history/:userId:', e);
    res.status(500).json({ error: 'DB error', details: e.message });
  }
});

module.exports = router; 