const express = require('express');
const mongoose = require('mongoose');
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const { uploadPrescriptionImages } = require('../controllers/prescriptionsController');
const ordersController = require('../controllers/ordersController');
const {
  getAllOrders,
  getOrder,
  createOrder,
  updateOrder,
  deleteOrder,
  getOrdersByStore,
  uploadOrderPrescription,
  updatePrescriptionStatus,
  getPrescriptionHistory,
  getPharmacistStoreOrders
} = ordersController;

const Order = require('../models/Order');
const advancedResults = require('../middleware/advancedResults');
const { auth, authorize } = require('../middleware/auth');
const { UnauthorizedError } = require('../utils/errors');

const router = express.Router();

// All routes below are protected
router.use(auth);

// Configure multer for order with prescription uploads
const orderUpload = multer({
  storage: multer.diskStorage({
    destination: (req, file, cb) => {
      const uploadDir = path.join(__dirname, '..', 'uploads', 'prescriptions');
      if (!fs.existsSync(uploadDir)) {
        fs.mkdirSync(uploadDir, { recursive: true });
      }
      cb(null, uploadDir);
    },
    filename: (req, file, cb) => {
      const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
      const ext = path.extname(file.originalname).toLowerCase();
      cb(null, 'rx-' + uniqueSuffix + ext);
    }
  }),
  fileFilter: (req, file, cb) => {
    // Accept images and PDFs
    if (file.mimetype.startsWith('image/') || file.mimetype === 'application/pdf') {
      cb(null, true);
    } else {
      cb(new Error('Only image files (jpg, jpeg, png, gif) and PDFs are allowed!'), false);
    }
  },
  limits: { fileSize: 10 * 1024 * 1024 } // 10MB limit
});

// POST /orders is allowed for all authenticated users
router.post('/', 
  orderUpload.any(), // Handle file uploads
  async (req, res, next) => {
    try {
      // Parse the order data if it exists and is a string
      if (req.body.order && typeof req.body.order === 'string') {
        try {
          const parsedOrder = JSON.parse(req.body.order);
          req.body = { ...parsedOrder, ...req.body };
        } catch (e) {
          console.error('Error parsing order JSON:', e);
          return res.status(400).json({
            success: false,
            error: 'Invalid order JSON format'
          });
        }
      }
      
      // Process uploaded files
      if (req.files && req.files.length > 0) {
        console.log('Processing uploaded files:', req.files);
        
        // Ensure the prescription object exists in the request body
        if (!req.body.prescription) {
          req.body.prescription = {};
        }
        
        // Initialize images array if it doesn't exist
        if (!req.body.prescription.images) {
          req.body.prescription.images = [];
        }
        
        // Process each uploaded file
        const uploadDir = path.join(__dirname, '../uploads/prescriptions');
        if (!fs.existsSync(uploadDir)) {
          fs.mkdirSync(uploadDir, { recursive: true });
        }
        
        // Add each file to the prescription images
        for (const file of req.files) {
          const fileExt = path.extname(file.originalname).toLowerCase();
          const fileName = `rx-${Date.now()}-${Math.round(Math.random() * 1E9)}${fileExt}`;
          const filePath = path.join(uploadDir, fileName);
          
          try {
            // Move the file from temp location to uploads directory
            await fs.promises.rename(file.path, filePath);
            
            // Add file info to prescription images
            req.body.prescription.images.push({
              path: `/uploads/prescriptions/${fileName}`,
              original_name: file.originalname,
              mimetype: file.mimetype,
              size: file.size,
              is_primary: req.body.prescription.images.length === 0, // First image is primary
              uploaded_at: new Date()
            });
            
            console.log(`Processed file: ${file.originalname} -> ${filePath}`);
          } catch (error) {
            console.error(`Error processing file ${file.originalname}:`, error);
            // Continue with other files if one fails
          }
        }
        
        console.log('Added files to prescription:', req.body.prescription.images);
      } else if (req.body.prescriptionId) {
        // If we have a prescription ID but no files, ensure we have a prescription object
        if (!req.body.prescription) {
          req.body.prescription = {
            _id: req.body.prescriptionId,
            images: []
          };
          
          // If there are files, add them to the prescription
          if (req.files && req.files.length > 0) {
            req.body.prescription.images = req.files.map(file => ({
              path: `/uploads/prescriptions/${file.filename}`,
              original_name: file.originalname,
              mimetype: file.mimetype,
              size: file.size,
              is_primary: true,
              uploaded_at: new Date()
            }));
          }
        }
      }
      
      // Log the parsed request body for debugging
      console.log('Parsed request body:', JSON.stringify({
        ...req.body,
        files: req.files ? req.files.map(f => f.filename) : []
      }, null, 2));
      
      next();
    } catch (error) {
      console.error('Error processing order data:', error);
      return res.status(400).json({
        success: false,
        error: 'Invalid order data format',
        details: error.message
      });
    }
  },
  createOrder
);

// Prescription upload and management routes
router.route('/:id/prescription')
  // Upload prescription for an order
  .post(auth, uploadPrescriptionImages, uploadOrderPrescription);

// Update prescription status (admin/pharmacist only)
router.route('/:id/prescription/status')
  .put(auth, authorize('admin', 'pharmacist'), updatePrescriptionStatus);

// Verify prescription (admin/pharmacist only)
router.put('/:id/verify-prescription', 
  auth, 
  authorize('admin', 'pharmacist'), 
  updatePrescriptionStatus
);

// Get prescription verification history (admin/pharmacist only)
router.get('/:id/prescription-history', 
  auth, 
  authorize('admin', 'pharmacist'), 
  getPrescriptionHistory
);

// Get orders for pharmacist's store
router.get('/pharmacist/store-orders', 
  auth,
  authorize('pharmacist'),
  getPharmacistStoreOrders
);

// Store-specific orders route (accessible by store owners, store managers, and admins)
router.get('/store/:storeId', 
  auth,
  authorize('store', 'store_manager', 'admin', 'superadmin'), 
  getOrdersByStore
);

// Create a separate route for picker_packers
router.get('/picker-orders', 
  async (req, res, next) => {
    try {
      // Check if user has picker_packer role
      if (req.user.role === 'picker_packer') {
        // Get the Order model
        const OrderModel = require('../models/Order');
        
        // Build query for picker packer
        const query = {
          status: { $in: ['approved', 'pending'] }, // Include both approved and pending orders
          store: req.user.store?._id || req.user.store
        };

        // Handle search
        if (req.query.search) {
          query.$or = [
            { orderNumber: { $regex: req.query.search, $options: 'i' } },
            { 'deliveryAddress.name': { $regex: req.query.search, $options: 'i' } },
            { 'deliveryAddress.phone': { $regex: req.query.search, $options: 'i' } }
          ];
        }

        // Pagination
        const page = parseInt(req.query.page, 10) || 1;
        const limit = parseInt(req.query.limit, 10) || 50;
        const startIndex = (page - 1) * limit;
        const endIndex = page * limit;
        
        try {
          // Add status filter for confirmed orders and ensure we only get orders for the current store
          const confirmedQuery = { 
            ...query, 
            status: 'CONFIRMED',
            store: new mongoose.Types.ObjectId(req.user.store) // Convert to ObjectId
          };
          
          console.log('Fetching confirmed orders with query:', JSON.stringify(confirmedQuery, null, 2));
          
          // Use BaseModel's static methods for querying
          let orders = await OrderModel.find(confirmedQuery)
            .populate('userId', 'name email phone')
            .populate('store', 'name')
            .sort({ createdAt: -1 })
            .skip((page - 1) * limit)
            .limit(limit)
            .lean();
            
          // Map userId to user to match frontend expectations
          orders = orders.map(order => ({
            ...order,
            user: order.userId,
            // Ensure we have all required fields for the frontend
            userId: undefined, // Remove userId to avoid confusion
            store: order.store || { name: 'N/A' },
            deliveryAddress: order.deliveryAddress || {}
          }));
            
          const total = await OrderModel.count(confirmedQuery);
          
          // Calculate pagination
          const totalPages = Math.ceil(total / limit);
          const pagination = {
            total,
            limit: parseInt(limit),
            page: parseInt(page),
            totalPages,
            hasNextPage: page < totalPages,
            hasPrevPage: page > 1,
            nextPage: page < totalPages ? page + 1 : null,
            prevPage: page > 1 ? page - 1 : null
          };

          return res.status(200).json({
            success: true,
            count: orders.length,
            pagination,
            data: orders
          });
        } catch (error) {
          console.error('Database error in picker-orders route:', error);
          throw new Error('Failed to fetch orders');
        }
      } else {
        throw new UnauthorizedError('Not authorized to access this route');
      }
    } catch (error) {
      console.error('Error in picker-orders route:', error);
      next(error);
    }
  }
);

// Regular orders route for admins and store managers
router.route('/')
  .get(
    authorize('admin', 'superadmin', 'store_manager', 'pharmacist'),
    (req, res, next) => {
      // For store managers, only show orders from their store
      if (req.user.role === 'store_manager' && req.user.store) {
        req.query.store = req.user.store._id || req.user.store;
      }
      next();
    },
    (req, res, next) => {
      // Create a custom middleware to handle the advancedResults call
      const middleware = advancedResults(Order, [
        { path: 'userId', select: 'name email' },
        { path: 'deliveryInfo.deliveryBoy', select: 'name phone' },
        { 
          path: 'items.item', 
          select: 'name price image brand category unit weight',
          populate: [
            { path: 'brand', select: 'name' },
            { path: 'category', select: 'name' },
            { path: 'unit', select: 'name shortCode' }
          ]
        },
        { path: 'store', select: 'name address' }
      ]);
      return middleware(req, res, next);
    },
    (req, res) => {
      // If we have results from advancedResults, return them
      if (res.advancedResults) {
        return res.status(200).json(res.advancedResults);
      }
      // Otherwise, call the controller
      return getAllOrders(req, res);
    }
  );

// Individual order routes (admin only)
router.route('/:id')
  .all(authorize('admin', 'superadmin'))
  .get(getOrder)
  .put(updateOrder)
  .delete(deleteOrder);

module.exports = router;
