const express = require('express');
const router = express.Router();
const { verifyToken } = require('../middleware/auth');
const Request = require('../models/Request');
const BuyProduct = require('../models/BuyProduct');
const path = require('path');
const fs = require('fs');
const multer = require('multer');
const mongoose = require('../../../utils/mongoose');

// Функция для логирования с проверкой DEV переменной
const log = (message, data = '') => {
  if (process.env.DEV === 'true') {
    if (data) {
      console.log(message, data);
    } else {
      console.log(message);
    }
  }
};

const REQUESTS_UPLOAD_ROOT = 'server/routers/remote-assets/uploads/requests';

const ensureDirectory = (dirPath) => {
  if (!fs.existsSync(dirPath)) {
    fs.mkdirSync(dirPath, { recursive: true });
  }
};

ensureDirectory(REQUESTS_UPLOAD_ROOT);

const MAX_REQUEST_FILE_SIZE = 20 * 1024 * 1024; // 20MB
const ALLOWED_REQUEST_MIME_TYPES = new Set([
  'application/pdf',
  'application/msword',
  'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  'application/vnd.ms-excel',
  'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  'text/csv',
]);

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    const subfolder = req.requestUploadSubfolder || '';
    const destinationDir = `${REQUESTS_UPLOAD_ROOT}/${subfolder}`;
    ensureDirectory(destinationDir);
    cb(null, destinationDir);
  },
  filename: (req, file, cb) => {
    const extension = path.extname(file.originalname) || '';
    const baseName = path
      .basename(file.originalname, extension)
      .replace(/[^a-zA-Z0-9-_]+/g, '_')
      .toLowerCase();
    cb(null, `${Date.now()}_${baseName}${extension}`);
  },
});

const upload = multer({
  storage,
  limits: {
    fileSize: MAX_REQUEST_FILE_SIZE,
  },
  fileFilter: (req, file, cb) => {
    if (ALLOWED_REQUEST_MIME_TYPES.has(file.mimetype)) {
      cb(null, true);
      return;
    }

    if (!req.invalidFiles) {
      req.invalidFiles = [];
    }
    req.invalidFiles.push(file.originalname);
    cb(null, false);
  },
});

const handleFilesUpload = (fieldName, subfolderResolver, maxCount = 10) => (req, res, next) => {
  req.invalidFiles = [];
  req.requestUploadSubfolder = subfolderResolver(req);

  upload.array(fieldName, maxCount)(req, res, (err) => {
    if (err) {
      console.error('[Requests] Multer error:', err.message);
      if (err.code === 'LIMIT_FILE_SIZE') {
        return res.status(400).json({ error: 'File is too large. Maximum size is 20MB.' });
      }
      return res.status(400).json({ error: err.message });
    }
    next();
  });
};

const cleanupUploadedFiles = async (req) => {
  if (!Array.isArray(req.files) || req.files.length === 0) {
    return;
  }

  const subfolder = req.requestUploadSubfolder || '';
  const removalTasks = req.files.map((file) => {
    const filePath = `${REQUESTS_UPLOAD_ROOT}/${subfolder}/${file.filename}`;
    return fs.promises.unlink(filePath).catch((error) => {
      if (error.code !== 'ENOENT') {
        console.error('[Requests] Failed to cleanup uploaded file:', error.message);
      }
    });
  });

  await Promise.all(removalTasks);
};

const mapFilesToMetadata = (req) => {
  if (!Array.isArray(req.files) || req.files.length === 0) {
    return [];
  }

  const subfolder = req.requestUploadSubfolder || '';
  return req.files.map((file) => {
    const relativePath = `requests/${subfolder}/${file.filename}`;
    return {
      id: `file-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
      name: file.originalname,
      url: `/uploads/${relativePath}`,
      type: file.mimetype,
      size: file.size,
      uploadedAt: new Date(),
      storagePath: relativePath,
    };
  });
};

const normalizeToArray = (value) => {
  if (!value) {
    return [];
  }
  if (Array.isArray(value)) {
    return value;
  }

  try {
    const parsed = JSON.parse(value);
    if (Array.isArray(parsed)) {
      return parsed;
    }
  } catch (error) {
    // ignore JSON parse errors
  }

  return String(value)
    .split(',')
    .map((item) => item.trim())
    .filter(Boolean);
};

const removeStoredFiles = async (files = []) => {
  if (!files || files.length === 0) {
    return;
  }

  const tasks = files
    .filter((file) => file && file.storagePath)
    .map((file) => {
      const absolutePath = `server/routers/remote-assets/uploads/${file.storagePath}`;
      return fs.promises.unlink(absolutePath).catch((error) => {
        if (error.code !== 'ENOENT') {
          console.error('[Requests] Failed to remove stored file:', error.message);
        }
      });
    });

  await Promise.all(tasks);
};

// GET /requests/sent - получить отправленные запросы
router.get('/sent', verifyToken, async (req, res) => {
  try {
    const companyId = req.companyId;

    if (!companyId) {
      return res.status(400).json({ error: 'Company ID is required' });
    }

    const requests = await Request.find({ senderCompanyId: companyId })
      .sort({ createdAt: -1 })
      .exec();

    log('[Requests] Returned', requests.length, 'sent requests for company', companyId);

    res.json(requests);
  } catch (error) {
    console.error('[Requests] Error fetching sent requests:', error.message);
    res.status(500).json({ error: error.message });
  }
});

// GET /requests/received - получить полученные запросы
router.get('/received', verifyToken, async (req, res) => {
  try {
    const companyId = req.companyId;

    if (!companyId) {
      return res.status(400).json({ error: 'Company ID is required' });
    }

    const requests = await Request.find({ recipientCompanyId: companyId })
      .sort({ createdAt: -1 })
      .exec();

    log('[Requests] Returned', requests.length, 'received requests for company', companyId);

    res.json(requests);
  } catch (error) {
    console.error('[Requests] Error fetching received requests:', error.message);
    res.status(500).json({ error: error.message });
  }
});

// POST /requests - создать запрос
router.post(
  '/',
  verifyToken,
  handleFilesUpload('files', (req) => `sent/${(req.companyId || 'unknown').toString()}`, 10),
  async (req, res) => {
    try {
      const senderCompanyId = req.companyId;
      const recipients = normalizeToArray(req.body.recipientCompanyIds);
      const text = (req.body.text || '').trim();
      const productId = req.body.productId ? String(req.body.productId) : null;
      let subject = (req.body.subject || '').trim();

      if (req.invalidFiles && req.invalidFiles.length > 0) {
        await cleanupUploadedFiles(req);
        return res.status(400).json({
          error: 'Unsupported file type. Allowed formats: PDF, DOC, DOCX, XLS, XLSX, CSV.',
          details: req.invalidFiles,
        });
      }

      if (!text) {
        await cleanupUploadedFiles(req);
        return res.status(400).json({ error: 'Request text is required' });
      }

      if (!recipients.length) {
        await cleanupUploadedFiles(req);
        return res.status(400).json({ error: 'At least one recipient is required' });
      }

      let uploadedFiles = mapFilesToMetadata(req);
      
      console.log('========================');
      console.log('[Requests] Initial uploadedFiles:', uploadedFiles.length);
      console.log('[Requests] ProductId:', productId);
      
      // Если есть productId, получаем данные товара
      if (productId) {
        try {
          const product = await BuyProduct.findById(productId);
          console.log('[Requests] Product found:', product ? product.name : 'null');
          console.log('[Requests] Product files count:', product?.files?.length || 0);
          if (product && product.files) {
            console.log('[Requests] Product files:', JSON.stringify(product.files, null, 2));
          }
          
          if (product) {
            // Берем subject из товара, если не указан
            if (!subject) {
              subject = product.name;
            }
            
            // Если файлы не загружены вручную, используем файлы из товара
            if (uploadedFiles.length === 0 && product.files && product.files.length > 0) {
              console.log('[Requests] ✅ Copying files from product...');
              // Копируем файлы из товара, изменяя путь для запроса
              uploadedFiles = product.files.map(file => ({
                id: file.id || `file-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
                name: file.name,
                url: file.url,
                type: file.type,
                size: file.size,
                uploadedAt: file.uploadedAt || new Date(),
                storagePath: file.storagePath || file.url.replace('/uploads/', ''),
              }));
              console.log('[Requests] ✅ Using', uploadedFiles.length, 'files from product:', productId);
              console.log('[Requests] ✅ Copied files:', JSON.stringify(uploadedFiles, null, 2));
            } else {
              console.log('[Requests] ❌ NOT copying files. uploadedFiles.length:', uploadedFiles.length, 'product.files.length:', product.files?.length || 0);
            }
          }
        } catch (lookupError) {
          console.error('[Requests] ❌ Failed to lookup product:', lookupError.message);
          console.error(lookupError.stack);
        }
      }
      
      console.log('[Requests] Final uploadedFiles for saving:', JSON.stringify(uploadedFiles, null, 2));
      console.log('========================');

      if (!subject) {
        await cleanupUploadedFiles(req);
        return res.status(400).json({ error: 'Subject is required' });
      }

      const results = [];
      for (const recipientCompanyId of recipients) {
        try {
          const request = new Request({
            senderCompanyId,
            recipientCompanyId,
            text,
            productId,
            subject,
            files: uploadedFiles,
            responseFiles: [],
            status: 'pending',
          });

          await request.save();
          results.push({
            companyId: recipientCompanyId,
            success: true,
            message: 'Request sent successfully',
          });

          log('[Requests] Request sent to company:', recipientCompanyId);
        } catch (err) {
          console.error('[Requests] Error storing request for company:', recipientCompanyId, err.message);
          results.push({
            companyId: recipientCompanyId,
            success: false,
            message: err.message,
          });
        }
      }

      const createdAt = new Date();

      res.status(201).json({
        id: 'bulk-' + Date.now(),
        text,
        subject,
        productId,
        files: uploadedFiles,
        result: results,
        createdAt,
      });
    } catch (error) {
      console.error('[Requests] Error creating request:', error.message);
      res.status(500).json({ error: error.message });
    }
  }
);

// PUT /requests/:id - ответить на запрос
router.put(
  '/:id',
  verifyToken,
  handleFilesUpload('responseFiles', (req) => `responses/${req.params.id || 'unknown'}`, 5),
  async (req, res) => {
    try {
      const { id } = req.params;
      console.log('[Requests] PUT /requests/:id called with id:', id);
      console.log('[Requests] Request body:', req.body);
      console.log('[Requests] Files:', req.files);
      console.log('[Requests] CompanyId:', req.companyId);
      
      const responseText = (req.body.response || '').trim();
      const statusRaw = (req.body.status || 'accepted').toLowerCase();
      const status = statusRaw === 'rejected' ? 'rejected' : 'accepted';
      
      console.log('[Requests] Response text:', responseText);
      console.log('[Requests] Status:', status);

      if (req.invalidFiles && req.invalidFiles.length > 0) {
        await cleanupUploadedFiles(req);
        return res.status(400).json({
          error: 'Unsupported file type. Allowed formats: PDF, DOC, DOCX, XLS, XLSX, CSV.',
          details: req.invalidFiles,
        });
      }

      if (!responseText) {
        await cleanupUploadedFiles(req);
        return res.status(400).json({ error: 'Response text is required' });
      }

      const request = await Request.findById(id);

      if (!request) {
        await cleanupUploadedFiles(req);
        return res.status(404).json({ error: 'Request not found' });
      }

      if (request.recipientCompanyId !== req.companyId) {
        await cleanupUploadedFiles(req);
        return res.status(403).json({ error: 'Not authorized' });
      }

      const uploadedResponseFiles = mapFilesToMetadata(req);
      console.log('[Requests] Uploaded response files count:', uploadedResponseFiles.length);
      console.log('[Requests] Uploaded response files:', JSON.stringify(uploadedResponseFiles, null, 2));

      if (uploadedResponseFiles.length > 0) {
        await removeStoredFiles(request.responseFiles || []);
        request.responseFiles = uploadedResponseFiles;
      }

      request.response = responseText;
      request.status = status;
      request.respondedAt = new Date();
      request.updatedAt = new Date();

      let savedRequest;
      try {
        savedRequest = await request.save();
        log('[Requests] Request responded:', id);
      } catch (saveError) {
        console.error('[Requests] Mongoose save failed, trying direct MongoDB update:', saveError.message);
        // Fallback: использовать MongoDB драйвер напрямую
        const updateData = {
          response: responseText,
          status: status,
          respondedAt: new Date(),
          updatedAt: new Date()
        };
        if (uploadedResponseFiles.length > 0) {
          updateData.responseFiles = uploadedResponseFiles;
        }
        
        const result = await mongoose.connection.collection('requests').findOneAndUpdate(
          { _id: new mongoose.Types.ObjectId(id) },
          { $set: updateData },
          { returnDocument: 'after' }
        );
        
        if (!result) {
          throw new Error('Failed to update request');
        }
        savedRequest = result;
        log('[Requests] Request responded via direct MongoDB update:', id);
      }

      res.json(savedRequest);
    } catch (error) {
      console.error('[Requests] Error responding to request:', error.message);
      console.error('[Requests] Error stack:', error.stack);
      if (error.name === 'ValidationError') {
        console.error('[Requests] Validation errors:', JSON.stringify(error.errors, null, 2));
      }
      res.status(500).json({ error: error.message });
    }
  }
);

// GET /requests/download/:id/:fileId - скачать файл ответа
router.get('/download/:id/:fileId', verifyToken, async (req, res) => {
  try {
    console.log('[Requests] Download request received:', {
      requestId: req.params.id,
      fileId: req.params.fileId,
      userId: req.userId,
      companyId: req.companyId,
    });

    const { id, fileId } = req.params;
    const request = await Request.findById(id);

    if (!request) {
      return res.status(404).json({ error: 'Request not found' });
    }

    // Проверяем, что пользователь имеет доступ к запросу (отправитель или получатель)
    if (request.senderCompanyId !== req.companyId && request.recipientCompanyId !== req.companyId) {
      return res.status(403).json({ error: 'Not authorized' });
    }

    // Ищем файл в responseFiles или в обычных files
    let file = request.responseFiles?.find((f) => f.id === fileId);
    if (!file) {
      file = request.files?.find((f) => f.id === fileId);
    }
    if (!file) {
      return res.status(404).json({ error: 'File not found' });
    }

    // Создаем абсолютный путь к файлу
    // Если storagePath не начинается с 'requests/', значит это файл из buy-products
    let fullPath = file.storagePath;
    if (!fullPath.startsWith('requests/')) {
      fullPath = `buy-products/${fullPath}`;
    }
    const filePath = path.resolve(`server/routers/remote-assets/uploads/${fullPath}`);

    console.log('[Requests] Trying to download file:', {
      fileId: file.id,
      fileName: file.name,
      storagePath: file.storagePath,
      absolutePath: filePath,
      exists: fs.existsSync(filePath),
    });

    // Проверяем существование файла
    if (!fs.existsSync(filePath)) {
      console.error('[Requests] File not found on disk:', filePath);
      return res.status(404).json({ error: 'File not found on disk' });
    }

    // Устанавливаем правильные заголовки для скачивания с поддержкой кириллицы
    const encodedFileName = encodeURIComponent(file.name);
    res.setHeader('Content-Type', file.type || 'application/octet-stream');
    res.setHeader('Content-Disposition', `attachment; filename*=UTF-8''${encodedFileName}`);
    res.setHeader('Content-Length', file.size);

    // Отправляем файл
    res.sendFile(filePath, (err) => {
      if (err) {
        console.error('[Requests] Error sending file:', err.message);
        if (!res.headersSent) {
          res.status(500).json({ error: 'Error sending file' });
        }
      } else {
        log('[Requests] File downloaded:', file.name);
      }
    });
  } catch (error) {
    console.error('[Requests] Error downloading file:', error.message);
    if (!res.headersSent) {
      res.status(500).json({ error: error.message });
    }
  }
});

// DELETE /requests/:id - удалить запрос
router.delete('/:id', verifyToken, async (req, res) => {
  try {
    const { id } = req.params;

    const request = await Request.findById(id);

    if (!request) {
      return res.status(404).json({ error: 'Request not found' });
    }

    // Может удалить отправитель или получатель
    if (request.senderCompanyId !== req.companyId && request.recipientCompanyId !== req.companyId) {
      return res.status(403).json({ error: 'Not authorized' });
    }

    await removeStoredFiles(request.files || []);
    await removeStoredFiles(request.responseFiles || []);

    await Request.findByIdAndDelete(id);

    log('[Requests] Request deleted:', id);

    res.json({ message: 'Request deleted successfully' });
  } catch (error) {
    console.error('[Requests] Error deleting request:', error.message);
    res.status(500).json({ error: error.message });
  }
});

module.exports = router;
