const express = require('express');
const router = express.Router();
const emailService = require('../services/emailService'); // Import email service

module.exports = (pool, query, authMiddleware) => {
  // Apply authentication middleware to all routes
  router.use(authMiddleware);
  
  // Get all orders (admin only)
  router.get('/', async (req, res, next) => {
    try {
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      const result = await query(`
        SELECT o.*, 
               u.email, u.first_name, u.last_name,
               COUNT(oi.id) AS item_count
        FROM orders o
        JOIN users u ON o.user_id = u.id
        LEFT JOIN order_items oi ON o.id = oi.order_id
        GROUP BY o.id, u.id
        ORDER BY o.created_at DESC
      `);
      
      res.json(result.rows);
    } catch (error) {
      next(error);
    }
  });
  
  // Get single order with items
  router.get('/:id', async (req, res, next) => {
    try {
      const { id } = req.params;
      
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Get order details with shipping information
      const orderResult = await query(`
        SELECT o.*, 
               u.email, 
               u.first_name, 
               u.last_name,
               (SELECT EXISTS(
                 SELECT 1 FROM notification_logs
                 WHERE order_id = o.id AND notification_type = 'shipping_notification'
               )) as notification_sent
        FROM orders o
        JOIN users u ON o.user_id = u.id
        WHERE o.id = $1
      `, [id]);
      
      if (orderResult.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Order not found'
        });
      }
      
      // Get order items with product details
      const itemsResult = await query(`
        SELECT oi.*, 
               p.name as product_name, 
               p.description as product_description,
               pc.name as product_category,
               (
                 SELECT json_agg(
                   json_build_object(
                     'id', pi.id,
                     'path', pi.image_path,
                     'isPrimary', pi.is_primary,
                     'displayOrder', pi.display_order
                   ) ORDER BY pi.display_order
                 )
                 FROM product_images pi
                 WHERE pi.product_id = p.id
               ) AS product_images
        FROM order_items oi
        JOIN products p ON oi.product_id = p.id
        JOIN product_categories pc ON p.category_id = pc.id
        WHERE oi.order_id = $1
      `, [id]);
      
      // Combine order with items
      const order = {
        ...orderResult.rows[0],
        items: itemsResult.rows
      };
      
      res.json(order);
    } catch (error) {
      next(error);
    }
  });
  
  // Update order status (simple version)
  router.patch('/:id', async (req, res, next) => {
    try {
      const { id } = req.params;
      const { status } = req.body;
      
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Validate status
      const validStatuses = ['pending', 'processing', 'shipped', 'delivered', 'cancelled', 'refunded'];
      if (!validStatuses.includes(status)) {
        return res.status(400).json({
          error: true,
          message: `Invalid status. Must be one of: ${validStatuses.join(', ')}`
        });
      }
      
      // Update order status
      const result = await query(`
        UPDATE orders
        SET status = $1, updated_at = NOW()
        WHERE id = $2
        RETURNING *
      `, [status, id]);
      
      if (result.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Order not found'
        });
      }
      
      res.json({
        message: 'Order status updated successfully',
        order: result.rows[0]
      });
    } catch (error) {
      next(error);
    }
  });
  
  // Update order status with shipping information and send notification
  router.patch('/:id/shipping', async (req, res, next) => {
    try {
      const { id } = req.params;
      const { status, shippingData, sendNotification } = req.body;
      
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Validate status
      const validStatuses = ['pending', 'processing', 'shipped', 'delivered', 'cancelled', 'refunded'];
      if (!validStatuses.includes(status)) {
        return res.status(400).json({
          error: true,
          message: `Invalid status. Must be one of: ${validStatuses.join(', ')}`
        });
      }
      
      // Get order with customer information before updating
      const orderResult = await query(`
        SELECT o.*, u.email, u.first_name, u.last_name
        FROM orders o
        JOIN users u ON o.user_id = u.id
        WHERE o.id = $1
      `, [id]);
      
      if (orderResult.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Order not found'
        });
      }
      
      const order = orderResult.rows[0];
      
      // Begin transaction
      const client = await pool.connect();
      
      try {
        await client.query('BEGIN');
        
        // Store shipping information as JSON in the database
        const updatedOrder = await client.query(`
          UPDATE orders
          SET 
            status = $1, 
            updated_at = NOW(),
            shipping_info = $2,
            shipping_date = $3
          WHERE id = $4
          RETURNING *
        `, [
          status, 
          JSON.stringify(shippingData),
          new Date(), 
          id
        ]);
        
        // If status is 'shipped' and notification requested, send email
        if (status === 'shipped' && sendNotification) {
          // Get order items for the email
          const itemsResult = await client.query(`
            SELECT oi.*, p.name as product_name, p.price as original_price
            FROM order_items oi
            JOIN products p ON oi.product_id = p.id
            WHERE oi.order_id = $1
          `, [id]);
          
          const orderItems = itemsResult.rows;
          
          // Generate items HTML table
          const itemsHtml = orderItems.map(item => `
            <tr>
              <td style="padding: 10px; border-bottom: 1px solid #eee;">${item.product_name}</td>
              <td style="padding: 10px; border-bottom: 1px solid #eee;">${item.quantity}</td>
              <td style="padding: 10px; border-bottom: 1px solid #eee;">$${parseFloat(item.price_at_purchase).toFixed(2)}</td>
              <td style="padding: 10px; border-bottom: 1px solid #eee;">$${(parseFloat(item.price_at_purchase) * item.quantity).toFixed(2)}</td>
            </tr>
          `).join('');
          
          // Generate carrier tracking link
          let trackingLink = '#';
          const shipper = shippingData.shipper || '';
          const trackingNumber = shippingData.trackingNumber;

          if (trackingNumber) {
            // Match exactly with the values from the dropdown
            switch(shipper) {
              case 'USPS':
                trackingLink = `https://tools.usps.com/go/TrackConfirmAction?tLabels=${trackingNumber}`;
                break;
              case 'UPS':
                trackingLink = `https://www.ups.com/track?tracknum=${trackingNumber}`;
                break;
              case 'FedEx':
                trackingLink = `https://www.fedex.com/apps/fedextrack/?tracknumbers=${trackingNumber}`;
                break;
              case 'DHL':
                trackingLink = `https://www.dhl.com/global-en/home/tracking.html?tracking-id=${trackingNumber}`;
                break;
              case 'Canada Post':
                trackingLink = `https://www.canadapost-postescanada.ca/track-reperage/en#/search?searchFor=${trackingNumber}`;
                break;
              case 'Purolator':
                trackingLink = `https://www.purolator.com/en/shipping/track/tracking-number/${trackingNumber}`;
                break;
              default:
                // For "other" or any carrier not in our list
                // Just make the tracking number text without a link
                trackingLink = '#';
                break;
            }
          }
          
          // Format shipping date
          const shippedDate = new Date(shippingData.shippedDate || new Date()).toLocaleDateString();
          
          // Send email notification using template system
          await emailService.sendShippingNotification({
            to: order.email,
            first_name: order.first_name,
            order_id: order.id.substring(0, 8),
            tracking_number: shippingData.trackingNumber || 'N/A',
            carrier: shippingData.shipper || 'Standard Shipping',
            tracking_link: trackingLink,
            shipped_date: shippedDate,
            estimated_delivery: shippingData.estimatedDelivery || 'N/A',
            items_html: itemsHtml,
            customer_message: shippingData.customerMessage || ''
          });
          
          // Log the notification in the database
          await client.query(`
            INSERT INTO notification_logs (order_id, notification_type, sent_at)
            VALUES ($1, $2, NOW())
          `, [id, 'shipping_notification']);
        }
        
        await client.query('COMMIT');
        
        res.json({
          message: 'Order status updated successfully',
          order: updatedOrder.rows[0]
        });
      } catch (error) {
        await client.query('ROLLBACK');
        throw error;
      } finally {
        client.release();
      }
    } catch (error) {
      console.error('Error updating order status with shipping:', error);
      next(error);
    }
  });
  
  return router;
};