const db = require('../models');
const { sendResponse } = require('../utils/response');
const asyncHandler = require('../middlewares/asyncHandler');
const { uploadDocumentFile, getFilePath, getFileUrl } = require('../middlewares/uploadMiddleware');
const fs = require('fs');
const path = require('path');
const masterController = require('./masterController');

// Create document controller using master controller
const documentController = masterController(db.Document, 'Document');

// Upload document file
exports.uploadFile = asyncHandler(async (req, res) => {
  uploadDocumentFile(req, res, async (err) => {
    if (err) {
      return sendResponse(res, 400, false, err.message, null);
    }

    if (!req.file) {
      return sendResponse(res, 400, false, 'No file uploaded', null);
    }

    const { id } = req.params;
    if (!id) {
      // Delete uploaded file if no ID provided
      if (req.file.path) {
        fs.unlinkSync(req.file.path);
      }
      return sendResponse(res, 400, false, 'Document ID is required', null);
    }

    try {
      // Find the document
      const document = await db.Document.findByPk(id);
      if (!document) {
        // Delete uploaded file if document not found
        if (req.file.path) {
          fs.unlinkSync(req.file.path);
        }
        return sendResponse(res, 404, false, 'Document not found', null);
      }

      // Delete old file if exists
      if (document.file_path) {
        const oldFilePath = getFilePath(document.file_path);
        if (fs.existsSync(oldFilePath)) {
          fs.unlinkSync(oldFilePath);
        }
      }

      // Calculate relative path from uploads directory
      const uploadsDir = path.join(__dirname, '../uploads');
      const relativePath = path.relative(uploadsDir, req.file.path).replace(/\\/g, '/');

      // Update document with file information
      await document.update({
        file_path: relativePath,
        file_name: req.file.originalname,
        file_size: req.file.size,
        file_type: req.file.mimetype,
        updated_by: req.user?.userId || null,
      });

      sendResponse(res, 200, true, 'Document file uploaded successfully', {
        document_id: document.id,
        file_url: getFileUrl(req.file.path),
        file_name: req.file.originalname,
        file_size: req.file.size,
        file_type: req.file.mimetype,
      });
    } catch (error) {
      // Delete uploaded file on error
      if (req.file.path) {
        fs.unlinkSync(req.file.path);
      }
      console.error('Error uploading document file:', error);
      sendResponse(res, 500, false, error.message || 'Failed to upload document file', null);
    }
  });
});

// Delete document file
exports.deleteFile = asyncHandler(async (req, res) => {
  const { id } = req.params;

  const document = await db.Document.findByPk(id);
  if (!document) {
    return sendResponse(res, 404, false, 'Document not found', null);
  }

  if (!document.file_path) {
    return sendResponse(res, 400, false, 'No file attached to this document', null);
  }

  try {
    // Delete file from filesystem
    const filePath = getFilePath(document.file_path);
    if (fs.existsSync(filePath)) {
      fs.unlinkSync(filePath);
    }

    // Update document to remove file information
    await document.update({
      file_path: null,
      file_name: null,
      file_size: null,
      file_type: null,
      updated_by: req.user?.userId || null,
    });

    sendResponse(res, 200, true, 'Document file deleted successfully', null);
  } catch (error) {
    console.error('Error deleting document file:', error);
    sendResponse(res, 500, false, error.message || 'Failed to delete document file', null);
  }
});

// Override create method to handle file upload
exports.create = asyncHandler(async (req, res) => {
  const data = req.body;
  
  if (data.created_by === undefined) {
    data.created_by = req.user?.userId || null;
  }
  if (data.updated_by === undefined) {
    data.updated_by = req.user?.userId || null;
  }

  if (data.company_id === undefined && req.user) {
    data.company_id = req.user.companyId;
  }

  // Create the document
  const document = await db.Document.create(data);

  // If file is uploaded, handle file upload
  if (req.file) {
    const uploadsDir = path.join(__dirname, '../uploads');
    const relativePath = path.relative(uploadsDir, req.file.path).replace(/\\/g, '/');
    
    await document.update({
      file_path: relativePath,
      file_name: req.file.originalname,
      file_size: req.file.size,
      file_type: req.file.mimetype,
    });
  }

  const created = await db.Document.findByPk(document.id);
  sendResponse(res, 201, true, 'Document created successfully', created);
});

// Override update method to handle file upload
exports.update = asyncHandler(async (req, res) => {
  const { id } = req.params;
  const data = req.body;
  
  if (data.updated_by === undefined) {
    data.updated_by = req.user?.userId || null;
  }

  const document = await db.Document.findByPk(id);
  if (!document) {
    return sendResponse(res, 404, false, 'Document not found', null);
  }

  // Delete old file if new file is being uploaded
  if (req.file && document.file_path) {
    const oldFilePath = getFilePath(document.file_path);
    if (fs.existsSync(oldFilePath)) {
      fs.unlinkSync(oldFilePath);
    }
  }

  // Update document data
  await document.update(data);

  // If file is uploaded, update file information
  if (req.file) {
    const uploadsDir = path.join(__dirname, '../uploads');
    const relativePath = path.relative(uploadsDir, req.file.path).replace(/\\/g, '/');
    
    await document.update({
      file_path: relativePath,
      file_name: req.file.originalname,
      file_size: req.file.size,
      file_type: req.file.mimetype,
    });
  }

  const updated = await db.Document.findByPk(id);
  sendResponse(res, 200, true, 'Document updated successfully', updated);
});

// Export all methods from master controller
exports.getAll = documentController.getAll;
exports.getById = documentController.getById;
exports.delete = documentController.delete;
