const express = require('express');
const router = express.Router();
const { Client } = require('ssh2');
const mysql = require('mysql2/promise');
const multer = require('multer');
const path = require('path');
const fs = require('fs');

// Create uploads directory if it doesn't exist
const uploadsDir = path.join('/var/www/html/inventory/uploads/products');
const reusableUploadsDir = path.join('/var/www/html/inventory/uploads/reusable');
fs.mkdirSync(uploadsDir, { recursive: true });
fs.mkdirSync(reusableUploadsDir, { recursive: true });

// Create a Map to track image upload times and their scheduled deletion
const imageUploadMap = new Map();

// Connection pooling and cache configuration
const connectionCache = {
  ssh: null,
  dbConnection: null,
  lastUsed: 0,
  isConnecting: false,
  connectionPromise: null,
  // Cache expiration time in milliseconds (5 minutes)
  expirationTime: 5 * 60 * 1000,
  // Cache for query results (key: query string, value: {data, timestamp})
  queryCache: new Map(),
  // Cache duration for different query types in milliseconds
  cacheDuration: {
    'field-options': 30 * 60 * 1000, // 30 minutes for field options
    'product-lines': 10 * 60 * 1000, // 10 minutes for product lines
    'sublines': 10 * 60 * 1000,      // 10 minutes for sublines
    'default': 60 * 1000             // 1 minute default
  }
};

// Function to schedule image deletion after 24 hours
const scheduleImageDeletion = (filename, filePath) => {
  // Only schedule deletion for images in the products folder
  if (!filePath.includes('/uploads/products/')) {
    console.log(`Skipping deletion for non-product image: ${filename}`);
    return;
  }

  // Delete any existing timeout for this file
  if (imageUploadMap.has(filename)) {
    clearTimeout(imageUploadMap.get(filename).timeoutId);
  }

  // Schedule deletion after 24 hours (24 * 60 * 60 * 1000 ms)
  const timeoutId = setTimeout(() => {
    console.log(`Auto-deleting image after 24 hours: ${filename}`);
    
    // Check if file exists before trying to delete
    if (fs.existsSync(filePath)) {
      try {
        fs.unlinkSync(filePath);
        console.log(`Successfully auto-deleted image: ${filename}`);
      } catch (error) {
        console.error(`Error auto-deleting image ${filename}:`, error);
      }
    } else {
      console.log(`File already deleted: ${filename}`);
    }
    
    // Remove from tracking map
    imageUploadMap.delete(filename);
  }, 24 * 60 * 60 * 1000); // 24 hours
  
  // Store upload time and timeout ID
  imageUploadMap.set(filename, {
    uploadTime: new Date(),
    timeoutId: timeoutId,
    filePath: filePath
  });
};

// Function to clean up scheduled deletions on server restart
const cleanupImagesOnStartup = () => {
  console.log('Checking for images to clean up...');
  
  // Check if uploads directory exists
  if (!fs.existsSync(uploadsDir)) {
    console.log('Uploads directory does not exist');
    return;
  }
  
  // Read all files in the directory
  fs.readdir(uploadsDir, (err, files) => {
    if (err) {
      console.error('Error reading uploads directory:', err);
      return;
    }
    
    const now = new Date();
    let countDeleted = 0;
    
    files.forEach(filename => {
      const filePath = path.join(uploadsDir, filename);
      
      // Get file stats
      try {
        const stats = fs.statSync(filePath);
        const fileCreationTime = stats.birthtime || stats.ctime; // birthtime might not be available on all systems
        const ageMs = now.getTime() - fileCreationTime.getTime();
        
        // If file is older than 24 hours, delete it
        if (ageMs > 24 * 60 * 60 * 1000) {
          fs.unlinkSync(filePath);
          countDeleted++;
          console.log(`Deleted old image on startup: ${filename} (age: ${Math.round(ageMs / (60 * 60 * 1000))} hours)`);
        } else {
          // Schedule deletion for remaining time
          const remainingMs = (24 * 60 * 60 * 1000) - ageMs;
          console.log(`Scheduling deletion for ${filename} in ${Math.round(remainingMs / (60 * 60 * 1000))} hours`);
          
          const timeoutId = setTimeout(() => {
            if (fs.existsSync(filePath)) {
              try {
                fs.unlinkSync(filePath);
                console.log(`Successfully auto-deleted scheduled image: ${filename}`);
              } catch (error) {
                console.error(`Error auto-deleting scheduled image ${filename}:`, error);
              }
            }
            imageUploadMap.delete(filename);
          }, remainingMs);
          
          imageUploadMap.set(filename, {
            uploadTime: fileCreationTime,
            timeoutId: timeoutId,
            filePath: filePath
          });
        }
      } catch (error) {
        console.error(`Error processing file ${filename}:`, error);
      }
    });
    
    console.log(`Cleanup completed: ${countDeleted} old images deleted, ${imageUploadMap.size} images scheduled for deletion`);
  });
};

// Run cleanup on server start
cleanupImagesOnStartup();

// Configure multer for file uploads
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    console.log(`Saving to: ${uploadsDir}`);
    cb(null, uploadsDir);
  },
  filename: function (req, file, cb) {
    // Create unique filename with original extension
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
    
    // Make sure we preserve the original file extension
    let fileExt = path.extname(file.originalname).toLowerCase();
    
    // Ensure there is a proper extension based on mimetype if none exists
    if (!fileExt) {
      switch (file.mimetype) {
        case 'image/jpeg': fileExt = '.jpg'; break;
        case 'image/png': fileExt = '.png'; break;
        case 'image/gif': fileExt = '.gif'; break;
        case 'image/webp': fileExt = '.webp'; break;
        default: fileExt = '.jpg'; // Default to jpg
      }
    }
    
    const fileName = `${req.body.upc || 'product'}-${uniqueSuffix}${fileExt}`;
    console.log(`Generated filename: ${fileName} with mimetype: ${file.mimetype}`);
    cb(null, fileName);
  }
});

const upload = multer({ 
  storage: storage,
  limits: {
    fileSize: 5 * 1024 * 1024, // 5MB max file size
  },
  fileFilter: function (req, file, cb) {
    // Accept only image files
    const filetypes = /jpeg|jpg|png|gif|webp/;
    const mimetype = filetypes.test(file.mimetype);
    const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
    
    if (mimetype && extname) {
      return cb(null, true);
    }
    cb(new Error('Only image files are allowed'));
  }
});

// Modified function to get a database connection with connection pooling
async function getDbConnection() {
  const now = Date.now();
  
  // Check if we need to refresh the connection due to inactivity
  const needsRefresh = !connectionCache.ssh || 
                       !connectionCache.dbConnection || 
                       (now - connectionCache.lastUsed > connectionCache.expirationTime);
  
  // If connection is still valid, update last used time and return existing connection
  if (!needsRefresh) {
    connectionCache.lastUsed = now;
    return {
      ssh: connectionCache.ssh,
      connection: connectionCache.dbConnection
    };
  }
  
  // If another request is already establishing a connection, wait for that promise
  if (connectionCache.isConnecting && connectionCache.connectionPromise) {
    try {
      await connectionCache.connectionPromise;
      return {
        ssh: connectionCache.ssh,
        connection: connectionCache.dbConnection
      };
    } catch (error) {
      // If that connection attempt failed, we'll try again below
      console.error('Error waiting for existing connection:', error);
    }
  }
  
  // Close existing connections if they exist
  if (connectionCache.dbConnection) {
    try {
      await connectionCache.dbConnection.end();
    } catch (error) {
      console.error('Error closing existing database connection:', error);
    }
  }
  
  if (connectionCache.ssh) {
    try {
      connectionCache.ssh.end();
    } catch (error) {
      console.error('Error closing existing SSH connection:', error);
    }
  }
  
  // Mark that we're establishing a new connection
  connectionCache.isConnecting = true;
  
  // Create a new promise for this connection attempt
  connectionCache.connectionPromise = setupSshTunnel().then(tunnel => {
    const { ssh, stream, dbConfig } = tunnel;
    
    return mysql.createConnection({
      ...dbConfig,
      stream
    }).then(connection => {
      // Store the new connections
      connectionCache.ssh = ssh;
      connectionCache.dbConnection = connection;
      connectionCache.lastUsed = Date.now();
      connectionCache.isConnecting = false;
      
      return {
        ssh,
        connection
      };
    });
  }).catch(error => {
    connectionCache.isConnecting = false;
    throw error;
  });
  
  // Wait for the connection to be established
  return connectionCache.connectionPromise;
}

// Helper function to get cached query results or execute query if not cached
async function getCachedQuery(cacheKey, queryType, queryFn) {
  // Get cache duration based on query type
  const cacheDuration = connectionCache.cacheDuration[queryType] || connectionCache.cacheDuration.default;
  
  // Check if we have a valid cached result
  const cachedResult = connectionCache.queryCache.get(cacheKey);
  const now = Date.now();
  
  if (cachedResult && (now - cachedResult.timestamp < cacheDuration)) {
    console.log(`Cache hit for ${queryType} query: ${cacheKey}`);
    return cachedResult.data;
  }
  
  // No valid cache found, execute the query
  console.log(`Cache miss for ${queryType} query: ${cacheKey}`);
  const result = await queryFn();
  
  // Cache the result
  connectionCache.queryCache.set(cacheKey, {
    data: result,
    timestamp: now
  });
  
  return result;
}

// Helper function to setup SSH tunnel - ONLY USED BY getDbConnection NOW
async function setupSshTunnel() {
  const sshConfig = {
    host: process.env.PROD_SSH_HOST,
    port: process.env.PROD_SSH_PORT || 22,
    username: process.env.PROD_SSH_USER,
    privateKey: process.env.PROD_SSH_KEY_PATH
      ? require('fs').readFileSync(process.env.PROD_SSH_KEY_PATH)
      : undefined,
    compress: true
  };

  const dbConfig = {
    host: process.env.PROD_DB_HOST || 'localhost',
    user: process.env.PROD_DB_USER,
    password: process.env.PROD_DB_PASSWORD,
    database: process.env.PROD_DB_NAME,
    port: process.env.PROD_DB_PORT || 3306,
    timezone: 'Z'
  };

  return new Promise((resolve, reject) => {
    const ssh = new Client();

    ssh.on('error', (err) => {
      console.error('SSH connection error:', err);
      reject(err);
    });

    ssh.on('ready', () => {
      ssh.forwardOut(
        '127.0.0.1',
        0,
        dbConfig.host,
        dbConfig.port,
        (err, stream) => {
          if (err) reject(err);
          resolve({ ssh, stream, dbConfig });
        }
      );
    }).connect(sshConfig);
  });
}

// Image upload endpoint
router.post('/upload-image', upload.single('image'), (req, res) => {
  try {
    if (!req.file) {
      return res.status(400).json({ error: 'No image file provided' });
    }

    // Log file information
    console.log('File uploaded:', {
      filename: req.file.filename,
      originalname: req.file.originalname,
      mimetype: req.file.mimetype,
      size: req.file.size,
      path: req.file.path
    });

    // Ensure the file exists
    const filePath = path.join(uploadsDir, req.file.filename);
    if (!fs.existsSync(filePath)) {
      return res.status(500).json({ error: 'File was not saved correctly' });
    }

    // Log file access permissions
    fs.access(filePath, fs.constants.R_OK, (err) => {
      if (err) {
        console.error('File permission issue:', err);
      } else {
        console.log('File is readable');
      }
    });

    // Create URL for the uploaded file - using an absolute URL with domain
    // This will generate a URL like: https://inventory.acot.site/uploads/products/filename.jpg
    const baseUrl = 'https://inventory.acot.site';
    const imageUrl = `${baseUrl}/uploads/products/${req.file.filename}`;
    
    // Schedule this image for deletion in 24 hours
    scheduleImageDeletion(req.file.filename, filePath);
    
    // Return success response with image URL
    res.status(200).json({
      success: true,
      imageUrl,
      fileName: req.file.filename,
      mimetype: req.file.mimetype,
      fullPath: filePath,
      message: 'Image uploaded successfully (will auto-delete after 24 hours)'
    });
    
  } catch (error) {
    console.error('Error uploading image:', error);
    res.status(500).json({ error: error.message || 'Failed to upload image' });
  }
});

// Image deletion endpoint
router.delete('/delete-image', (req, res) => {
  try {
    const { filename } = req.body;
    
    if (!filename) {
      return res.status(400).json({ error: 'Filename is required' });
    }
    
    const filePath = path.join(uploadsDir, filename);
    
    // Check if file exists
    if (!fs.existsSync(filePath)) {
      return res.status(404).json({ error: 'File not found' });
    }
    
    // Only allow deletion of images in the products folder
    if (!filePath.includes('/uploads/products/')) {
      return res.status(403).json({ 
        error: 'Cannot delete images outside the products folder',
        message: 'This image is in a protected folder and cannot be deleted through this endpoint'
      });
    }
    
    // Delete the file
    fs.unlinkSync(filePath);
    
    // Clear any scheduled deletion for this file
    if (imageUploadMap.has(filename)) {
      clearTimeout(imageUploadMap.get(filename).timeoutId);
      imageUploadMap.delete(filename);
    }
    
    // Return success response
    res.status(200).json({
      success: true,
      message: 'Image deleted successfully'
    });
    
  } catch (error) {
    console.error('Error deleting image:', error);
    res.status(500).json({ error: error.message || 'Failed to delete image' });
  }
});

// Get all options for import fields
router.get('/field-options', async (req, res) => {
    try {
        // Use cached connection
        const { connection } = await getDbConnection();

        const cacheKey = 'field-options';
        const result = await getCachedQuery(cacheKey, 'field-options', async () => {
            // Fetch companies (type 1)
            const [companies] = await connection.query(`
                SELECT cat_id, name 
                FROM product_categories 
                WHERE type = 1 
                ORDER BY name
            `);

            // Fetch artists (type 40)
            const [artists] = await connection.query(`
                SELECT cat_id, name 
                FROM product_categories 
                WHERE type = 40 
                ORDER BY name
            `);

            // Fetch sizes (type 50)
            const [sizes] = await connection.query(`
                SELECT cat_id, name 
                FROM product_categories 
                WHERE type = 50 
                ORDER BY name
            `);

            // Fetch themes with subthemes
            const [themes] = await connection.query(`
                SELECT t.cat_id, t.name AS display_name, t.type, t.name AS sort_theme, 
                       '' AS sort_subtheme, 1 AS level_order 
                FROM product_categories t 
                WHERE t.type = 20 
                UNION ALL 
                SELECT ts.cat_id, CONCAT(t.name,' - ',ts.name) AS display_name, ts.type,
                       t.name AS sort_theme, ts.name AS sort_subtheme, 2 AS level_order 
                FROM product_categories ts 
                JOIN product_categories t ON ts.master_cat_id = t.cat_id 
                WHERE ts.type = 21 AND t.type = 20 
                ORDER BY sort_theme, sort_subtheme
            `);

            // Fetch categories with all levels
            const [categories] = await connection.query(`
                SELECT s.cat_id, s.name AS display_name, s.type, s.name AS sort_section,
                       '' AS sort_category, '' AS sort_subcategory, '' AS sort_subsubcategory,
                       1 AS level_order 
                FROM product_categories s 
                WHERE s.type = 10 
                UNION ALL 
                SELECT c.cat_id, CONCAT(s.name,' - ',c.name) AS display_name, c.type,
                       s.name AS sort_section, c.name AS sort_category, '' AS sort_subcategory,
                       '' AS sort_subsubcategory, 2 AS level_order 
                FROM product_categories c 
                JOIN product_categories s ON c.master_cat_id = s.cat_id 
                WHERE c.type = 11 AND s.type = 10 
                UNION ALL 
                SELECT sc.cat_id, CONCAT(s.name,' - ',c.name,' - ',sc.name) AS display_name,
                       sc.type, s.name AS sort_section, c.name AS sort_category,
                       sc.name AS sort_subcategory, '' AS sort_subsubcategory, 3 AS level_order 
                FROM product_categories sc 
                JOIN product_categories c ON sc.master_cat_id = c.cat_id 
                JOIN product_categories s ON c.master_cat_id = s.cat_id 
                WHERE sc.type = 12 AND c.type = 11 AND s.type = 10 
                UNION ALL 
                SELECT ssc.cat_id, CONCAT(s.name,' - ',c.name,' - ',sc.name,' - ',ssc.name) AS display_name,
                       ssc.type, s.name AS sort_section, c.name AS sort_category,
                       sc.name AS sort_subcategory, ssc.name AS sort_subsubcategory, 4 AS level_order 
                FROM product_categories ssc 
                JOIN product_categories sc ON ssc.master_cat_id = sc.cat_id 
                JOIN product_categories c ON sc.master_cat_id = c.cat_id 
                JOIN product_categories s ON c.master_cat_id = s.cat_id 
                WHERE ssc.type = 13 AND sc.type = 12 AND c.type = 11 AND s.type = 10 
                ORDER BY sort_section, sort_category, sort_subcategory, sort_subsubcategory
            `);

            // Fetch colors
            const [colors] = await connection.query(`
                SELECT color, name, hex_color 
                FROM product_color_list 
                ORDER BY \`order\`
            `);

            // Fetch suppliers
            const [suppliers] = await connection.query(`
                SELECT supplierid as value, companyname as label 
                FROM suppliers 
                WHERE companyname <> '' 
                ORDER BY companyname
            `);

            // Fetch tax categories
            const [taxCategories] = await connection.query(`
                SELECT CAST(tax_code_id AS CHAR) as value, name as label 
                FROM product_tax_codes 
                ORDER BY tax_code_id = 0 DESC, name
            `);

            // Format and return all options
            return {
                companies: companies.map(c => ({ label: c.name, value: c.cat_id.toString() })),
                artists: artists.map(a => ({ label: a.name, value: a.cat_id.toString() })),
                sizes: sizes.map(s => ({ label: s.name, value: s.cat_id.toString() })),
                themes: themes.map(t => ({ 
                    label: t.display_name, 
                    value: t.cat_id.toString(),
                    type: t.type,
                    level: t.level_order
                })),
                categories: categories.map(c => ({ 
                    label: c.display_name, 
                    value: c.cat_id.toString(),
                    type: c.type,
                    level: c.level_order
                })),
                colors: colors.map(c => ({ 
                    label: c.name, 
                    value: c.color,
                    hexColor: c.hex_color 
                })),
                suppliers: suppliers,
                taxCategories: taxCategories,
                shippingRestrictions: [
                    { label: "None", value: "0" },
                    { label: "US Only", value: "1" },
                    { label: "Limited Quantity", value: "2" },
                    { label: "US/CA Only", value: "3" },
                    { label: "No FedEx 2 Day", value: "4" },
                    { label: "North America Only", value: "5" }
                ]
            };
        });

        // Add debugging to verify category types
        console.log(`Returning ${result.categories.length} categories with types: ${Array.from(new Set(result.categories.map(c => c.type))).join(', ')}`);
        
        res.json(result);
    } catch (error) {
        console.error('Error fetching import field options:', error);
        res.status(500).json({ error: 'Failed to fetch import field options' });
    }
});

// Get product lines for a specific company
router.get('/product-lines/:companyId', async (req, res) => {
    try {
        // Use cached connection
        const { connection } = await getDbConnection();

        const companyId = req.params.companyId;
        const cacheKey = `product-lines-${companyId}`;
        
        const lines = await getCachedQuery(cacheKey, 'product-lines', async () => {
            const [queryResult] = await connection.query(`
                SELECT cat_id as value, name as label 
                FROM product_categories 
                WHERE type = 2 
                AND master_cat_id = ? 
                ORDER BY name
            `, [companyId]);
            
            return queryResult.map(l => ({ label: l.label, value: l.value.toString() }));
        });

        res.json(lines);
    } catch (error) {
        console.error('Error fetching product lines:', error);
        res.status(500).json({ error: 'Failed to fetch product lines' });
    }
});

// Get sublines for a specific product line
router.get('/sublines/:lineId', async (req, res) => {
    try {
        // Use cached connection
        const { connection } = await getDbConnection();

        const lineId = req.params.lineId;
        const cacheKey = `sublines-${lineId}`;
        
        const sublines = await getCachedQuery(cacheKey, 'sublines', async () => {
            const [queryResult] = await connection.query(`
                SELECT cat_id as value, name as label 
                FROM product_categories 
                WHERE type = 3 
                AND master_cat_id = ? 
                ORDER BY name
            `, [lineId]);
            
            return queryResult.map(s => ({ label: s.label, value: s.value.toString() }));
        });

        res.json(sublines);
    } catch (error) {
        console.error('Error fetching sublines:', error);
        res.status(500).json({ error: 'Failed to fetch sublines' });
    }
});

// Add a simple endpoint to check file existence and permissions
router.get('/check-file/:filename', (req, res) => {
  const { filename } = req.params;
  
  // Prevent directory traversal
  if (filename.includes('..') || filename.includes('/')) {
    return res.status(400).json({ error: 'Invalid filename' });
  }
  
  // First check in products directory
  let filePath = path.join(uploadsDir, filename);
  let exists = fs.existsSync(filePath);
  
  // If not found in products, check in reusable directory
  if (!exists) {
    filePath = path.join(reusableUploadsDir, filename);
    exists = fs.existsSync(filePath);
  }
  
  try {
    // Check if file exists
    if (!exists) {
      return res.status(404).json({ 
        error: 'File not found', 
        path: filePath,
        exists: false,
        readable: false 
      });
    }
    
    // Check if file is readable
    fs.accessSync(filePath, fs.constants.R_OK);
    
    // Get file stats
    const stats = fs.statSync(filePath);
    
    return res.json({
      filename,
      path: filePath,
      exists: true,
      readable: true,
      isFile: stats.isFile(),
      isDirectory: stats.isDirectory(),
      size: stats.size,
      created: stats.birthtime,
      modified: stats.mtime,
      permissions: stats.mode.toString(8)
    });
  } catch (error) {
    return res.status(500).json({ 
      error: error.message,
      path: filePath,
      exists: fs.existsSync(filePath),
      readable: false
    });
  }
});

// List all files in uploads directory
router.get('/list-uploads', (req, res) => {
  try {
    const { directory = 'products' } = req.query;
    
    // Determine which directory to list
    let targetDir;
    if (directory === 'reusable') {
      targetDir = reusableUploadsDir;
    } else {
      targetDir = uploadsDir; // default to products
    }
    
    if (!fs.existsSync(targetDir)) {
      return res.status(404).json({ error: 'Uploads directory not found', path: targetDir });
    }
    
    const files = fs.readdirSync(targetDir);
    const fileDetails = files.map(file => {
      const filePath = path.join(targetDir, file);
      try {
        const stats = fs.statSync(filePath);
        return {
          filename: file,
          isFile: stats.isFile(),
          isDirectory: stats.isDirectory(),
          size: stats.size,
          created: stats.birthtime,
          modified: stats.mtime,
          permissions: stats.mode.toString(8)
        };
      } catch (error) {
        return { filename: file, error: error.message };
      }
    });
    
    return res.json({
      directory: targetDir,
      type: directory,
      count: files.length,
      files: fileDetails
    });
  } catch (error) {
    return res.status(500).json({ error: error.message });
  }
});

// Search products from production database
router.get('/search-products', async (req, res) => {
  const { q, company, dateRange } = req.query;
  
  if (!q) {
    return res.status(400).json({ error: 'Search term is required' });
  }
  
  try {
    const { connection } = await getDbConnection();
    
    // Build WHERE clause with additional filters
    let whereClause = `
      WHERE (
        p.description LIKE ? OR
        p.itemnumber LIKE ? OR
        p.upc LIKE ? OR
        pc1.name LIKE ? OR
        s.companyname LIKE ?
      )`;
    
    // Add company filter if provided
    if (company) {
      whereClause += ` AND p.company = ${connection.escape(company)}`;
    }
    
    // Add date range filter if provided
    if (dateRange) {
      let dateCondition;
      const now = new Date();
      
      switch(dateRange) {
        case '1week':
          // Last week: date is after (current date - 7 days)
          const weekAgo = new Date(now);
          weekAgo.setDate(now.getDate() - 7);
          dateCondition = `p.datein >= ${connection.escape(weekAgo.toISOString().slice(0, 10))}`;
          break;
        case '1month':
          // Last month: date is after (current date - 30 days)
          const monthAgo = new Date(now);
          monthAgo.setDate(now.getDate() - 30);
          dateCondition = `p.datein >= ${connection.escape(monthAgo.toISOString().slice(0, 10))}`;
          break;
        case '2months':
          // Last 2 months: date is after (current date - 60 days)
          const twoMonthsAgo = new Date(now);
          twoMonthsAgo.setDate(now.getDate() - 60);
          dateCondition = `p.datein >= ${connection.escape(twoMonthsAgo.toISOString().slice(0, 10))}`;
          break;
        case '3months':
          // Last 3 months: date is after (current date - 90 days)
          const threeMonthsAgo = new Date(now);
          threeMonthsAgo.setDate(now.getDate() - 90);
          dateCondition = `p.datein >= ${connection.escape(threeMonthsAgo.toISOString().slice(0, 10))}`;
          break;
        case '6months':
          // Last 6 months: date is after (current date - 180 days)
          const sixMonthsAgo = new Date(now);
          sixMonthsAgo.setDate(now.getDate() - 180);
          dateCondition = `p.datein >= ${connection.escape(sixMonthsAgo.toISOString().slice(0, 10))}`;
          break;
        case '1year':
          // Last year: date is after (current date - 365 days)
          const yearAgo = new Date(now);
          yearAgo.setDate(now.getDate() - 365);
          dateCondition = `p.datein >= ${connection.escape(yearAgo.toISOString().slice(0, 10))}`;
          break;
        default:
          // If an unrecognized value is provided, don't add a date condition
          dateCondition = null;
      }
      
      if (dateCondition) {
        whereClause += ` AND ${dateCondition}`;
      }
    }
    
    // Special case for wildcard search
    const isWildcardSearch = q === '*';
    const searchPattern = isWildcardSearch ? '%' : `%${q}%`;
    const exactPattern = isWildcardSearch ? '%' : q;
    
    // Search for products based on various fields
    const query = `
      SELECT 
        p.pid,
        p.description AS title,
        p.notes AS description,
        p.itemnumber AS sku,
        p.upc AS barcode,
        p.harmonized_tariff_code,
        pcp.price_each AS price,
        p.sellingprice AS regular_price,
        CASE 
          WHEN EXISTS (SELECT 1 FROM product_inventory WHERE pid = p.pid AND count > 0) 
          THEN (SELECT ROUND(AVG(costeach), 5) FROM product_inventory WHERE pid = p.pid AND count > 0)
          ELSE (SELECT costeach FROM product_inventory WHERE pid = p.pid ORDER BY daterec DESC LIMIT 1)
        END AS cost_price,
        s.companyname AS vendor,
        sid.supplier_itemnumber AS vendor_reference,
        sid.notions_itemnumber AS notions_reference,
        sid.supplier_id AS supplier,
        sid.notions_case_pack AS case_qty,
        pc1.name AS brand,
        p.company AS brand_id,
        pc2.name AS line,
        p.line AS line_id,
        pc3.name AS subline,
        p.subline AS subline_id,
        pc4.name AS artist,
        p.artist AS artist_id,
        COALESCE(CASE 
          WHEN sid.supplier_id = 92 THEN sid.notions_qty_per_unit
          ELSE sid.supplier_qty_per_unit
        END, sid.notions_qty_per_unit) AS moq,
        p.weight,
        p.length,
        p.width,
        p.height,
        p.country_of_origin,
        ci.totalsold AS total_sold,
        p.datein AS first_received,
        pls.date_sold AS date_last_sold,
        IF(p.tax_code IS NULL, '', CAST(p.tax_code AS CHAR)) AS tax_code,
        CAST(p.size_cat AS CHAR) AS size_cat,
        CAST(p.shipping_restrictions AS CHAR) AS shipping_restrictions
      FROM products p
      LEFT JOIN product_current_prices pcp ON p.pid = pcp.pid AND pcp.active = 1
      LEFT JOIN supplier_item_data sid ON p.pid = sid.pid
      LEFT JOIN suppliers s ON sid.supplier_id = s.supplierid
      LEFT JOIN product_categories pc1 ON p.company = pc1.cat_id
      LEFT JOIN product_categories pc2 ON p.line = pc2.cat_id
      LEFT JOIN product_categories pc3 ON p.subline = pc3.cat_id
      LEFT JOIN product_categories pc4 ON p.artist = pc4.cat_id
      LEFT JOIN product_last_sold pls ON p.pid = pls.pid
      LEFT JOIN current_inventory ci ON p.pid = ci.pid
      ${whereClause}
      GROUP BY p.pid
      ${isWildcardSearch ? 'ORDER BY p.datein DESC' : `
      ORDER BY 
        CASE 
          WHEN p.description LIKE ? THEN 1
          WHEN p.itemnumber = ? THEN 2
          WHEN p.upc = ? THEN 3
          WHEN pc1.name LIKE ? THEN 4
          WHEN s.companyname LIKE ? THEN 5
          ELSE 6
        END
      `}
    `;
    
    // Prepare query parameters based on whether it's a wildcard search
    let queryParams;
    if (isWildcardSearch) {
      queryParams = [
        searchPattern, // LIKE for description
        searchPattern, // LIKE for itemnumber
        searchPattern, // LIKE for upc
        searchPattern, // LIKE for brand name
        searchPattern  // LIKE for company name
      ];
    } else {
      queryParams = [
        searchPattern, // LIKE for description
        searchPattern, // LIKE for itemnumber
        searchPattern, // LIKE for upc
        searchPattern, // LIKE for brand name
        searchPattern, // LIKE for company name
        // For ORDER BY clause
        searchPattern, // LIKE for description
        exactPattern, // Exact match for itemnumber
        exactPattern, // Exact match for upc
        searchPattern, // LIKE for brand name
        searchPattern  // LIKE for company name
      ];
    }
    
    const [results] = await connection.query(query, queryParams);
    
    // Debug log to check values
    if (results.length > 0) {
      console.log('Product search result sample fields:', {
        pid: results[0].pid,
        tax_code: results[0].tax_code,
        tax_code_type: typeof results[0].tax_code,
        tax_code_value: `Value: '${results[0].tax_code}'`,
        size_cat: results[0].size_cat,
        shipping_restrictions: results[0].shipping_restrictions,
        supplier: results[0].supplier,
        case_qty: results[0].case_qty,
        moq: results[0].moq
      });
    }
    
    res.json(results);
  } catch (error) {
    console.error('Error searching products:', error);
    res.status(500).json({ error: 'Failed to search products' });
  }
});

// Endpoint to check UPC and generate item number
router.get('/check-upc-and-generate-sku', async (req, res) => {
  const { upc, supplierId } = req.query;
  
  if (!upc || !supplierId) {
    return res.status(400).json({ error: 'UPC and supplier ID are required' });
  }
  
  try {
    const { connection } = await getDbConnection();
    
    // Step 1: Check if the UPC already exists
    const [upcCheck] = await connection.query(
      'SELECT pid, itemnumber FROM products WHERE upc = ? LIMIT 1',
      [upc]
    );
    
    if (upcCheck.length > 0) {
      return res.status(409).json({ 
        error: 'UPC already exists', 
        existingProductId: upcCheck[0].pid,
        existingItemNumber: upcCheck[0].itemnumber
      });
    }
    
    // Step 2: Generate item number - supplierId-last5DigitsOfUPC minus last digit
    let itemNumber = '';
    const upcStr = String(upc);
    
    // Extract the last 5 digits of the UPC, removing the last digit (checksum)
    // So we get 5 digits from positions: length-6 to length-2
    if (upcStr.length >= 6) {
      const lastFiveMinusOne = upcStr.substring(upcStr.length - 6, upcStr.length - 1);
      itemNumber = `${supplierId}-${lastFiveMinusOne}`;
    } else if (upcStr.length >= 5) {
      // If UPC is shorter, use as many digits as possible
      const digitsToUse = upcStr.substring(0, upcStr.length - 1);
      itemNumber = `${supplierId}-${digitsToUse}`;
    } else {
      // Very short UPC, just use the whole thing
      itemNumber = `${supplierId}-${upcStr}`;
    }
    
    // Step 3: Check if the generated item number exists
    const [itemNumberCheck] = await connection.query(
      'SELECT pid FROM products WHERE itemnumber = ? LIMIT 1',
      [itemNumber]
    );
    
    // Step 4: If the item number exists, modify it to use the last 5 digits of the UPC
    if (itemNumberCheck.length > 0) {
      console.log(`Item number ${itemNumber} already exists, using alternative format`);
      
      if (upcStr.length >= 5) {
        // Use the last 5 digits (including the checksum)
        const lastFive = upcStr.substring(upcStr.length - 5);
        itemNumber = `${supplierId}-${lastFive}`;
        
        // Check again if this new item number also exists
        const [altItemNumberCheck] = await connection.query(
          'SELECT pid FROM products WHERE itemnumber = ? LIMIT 1',
          [itemNumber]
        );
        
        if (altItemNumberCheck.length > 0) {
          // If even the alternative format exists, add a timestamp suffix for uniqueness
          const timestamp = Date.now().toString().substring(8, 13); // Get last 5 digits of timestamp
          itemNumber = `${supplierId}-${timestamp}`;
          console.log(`Alternative item number also exists, using timestamp: ${itemNumber}`);
        }
      } else {
        // For very short UPCs, add a timestamp
        const timestamp = Date.now().toString().substring(8, 13); // Get last 5 digits of timestamp
        itemNumber = `${supplierId}-${timestamp}`;
      }
    }
    
    // Return the generated item number
    res.json({ 
      success: true, 
      itemNumber, 
      upc,
      supplierId
    });
    
  } catch (error) {
    console.error('Error checking UPC and generating item number:', error);
    res.status(500).json({ 
      error: 'Failed to check UPC and generate item number',
      details: error.message
    });
  }
});

// Get product categories for a specific product
router.get('/product-categories/:pid', async (req, res) => {
  try {
    const { pid } = req.params;
    
    if (!pid || isNaN(parseInt(pid))) {
      return res.status(400).json({ error: 'Valid product ID is required' });
    }
    
    // Use the getDbConnection function instead of getPool
    const { connection } = await getDbConnection();
    
    // Query to get categories for a specific product
    const query = `
      SELECT pc.cat_id, pc.name, pc.type, pc.combined_name, pc.master_cat_id
      FROM product_category_index pci
      JOIN product_categories pc ON pci.cat_id = pc.cat_id
      WHERE pci.pid = ?
      ORDER BY pc.type, pc.name
    `;
    
    const [rows] = await connection.query(query, [pid]);
    
    // Add debugging to log category types
    const categoryTypes = rows.map(row => row.type);
    const uniqueTypes = [...new Set(categoryTypes)];
    console.log(`Product ${pid} has ${rows.length} categories with types: ${uniqueTypes.join(', ')}`);
    console.log('Categories:', rows.map(row => ({ id: row.cat_id, name: row.name, type: row.type })));
    
    // Check for parent categories to filter out deals and black friday
    const sectionQuery = `
      SELECT pc.cat_id, pc.name 
      FROM product_categories pc
      WHERE pc.type = 10 AND (LOWER(pc.name) LIKE '%deal%' OR LOWER(pc.name) LIKE '%black friday%')
    `;
    
    const [dealSections] = await connection.query(sectionQuery);
    const dealSectionIds = dealSections.map(section => section.cat_id);
    
    console.log('Filtering out categories from deal sections:', dealSectionIds);
    
    // Filter out categories from deals and black friday sections
    const filteredCategories = rows.filter(category => {
      // Direct check for top-level deal sections
      if (category.type === 10) {
        return !dealSectionIds.some(id => id === category.cat_id);
      }
      
      // For categories (type 11), check if their parent is a deal section
      if (category.type === 11) {
        return !dealSectionIds.some(id => id === category.master_cat_id);
      }
      
      // For subcategories (type 12), get their parent category first
      if (category.type === 12) {
        const parentId = category.master_cat_id;
        // Find the parent category in our rows
        const parentCategory = rows.find(c => c.cat_id === parentId);
        // If parent not found or parent's parent is not a deal section, keep it
        return !parentCategory || !dealSectionIds.some(id => id === parentCategory.master_cat_id);
      }
      
      // For subsubcategories (type 13), check their hierarchy manually
      if (category.type === 13) {
        const parentId = category.master_cat_id;
        // Find the parent subcategory
        const parentSubcategory = rows.find(c => c.cat_id === parentId);
        if (!parentSubcategory) return true;
        
        // Find the grandparent category
        const grandparentId = parentSubcategory.master_cat_id;
        const grandparentCategory = rows.find(c => c.cat_id === grandparentId);
        // If grandparent not found or grandparent's parent is not a deal section, keep it
        return !grandparentCategory || !dealSectionIds.some(id => id === grandparentCategory.master_cat_id);
      }
      
      // Keep all other category types
      return true;
    });
    
    console.log(`Filtered out ${rows.length - filteredCategories.length} deal/black friday categories`);
    
    // Format the response to match the expected format in the frontend
    const categories = filteredCategories.map(category => ({
      value: category.cat_id.toString(),
      label: category.name,
      type: category.type,
      combined_name: category.combined_name
    }));
    
    res.json(categories);
  } catch (error) {
    console.error('Error fetching product categories:', error);
    res.status(500).json({ 
      error: 'Failed to fetch product categories',
      details: error.message 
    });
  }
});

module.exports = router; 