const express = require('express');
const multer = require('multer');
const path = require('path');
const cors = require('cors');
const morgan = require('morgan');
const config = require('./config');
const { query, pool } = require('./db')
const authMiddleware = require('./middleware/auth');
const adminAuthMiddleware = require('./middleware/adminAuth');
const settingsAdminRoutes = require('./routes/settingsAdmin');
const SystemSettings = require('./models/SystemSettings');
const fs = require('fs');
// services
const notificationService = require('./services/notificationService');
const emailService = require('./services/emailService');

// routes
const stripePaymentRoutes = require('./routes/stripePayment');
const productRoutes = require('./routes/products');
const authRoutes = require('./routes/auth');
const cartRoutes = require('./routes/cart');
const productAdminRoutes = require('./routes/productAdmin');
const categoryAdminRoutes = require('./routes/categoryAdmin');
const usersAdminRoutes = require('./routes/userAdmin');
const ordersAdminRoutes = require('./routes/orderAdmin');
const couponsAdminRoutes = require('./routes/couponAdmin');
const userOrdersRoutes = require('./routes/userOrders');
const shippingRoutes = require('./routes/shipping');
const blogRoutes = require('./routes/blog');
const blogAdminRoutes = require('./routes/blogAdmin');
const blogCommentsAdminRoutes = require('./routes/blogCommentsAdmin');
const productReviewsRoutes = require('./routes/productReviews');
const productReviewsAdminRoutes = require('./routes/productReviewsAdmin');
const emailTemplatesAdminRoutes = require('./routes/emailTemplatesAdmin');
const publicSettingsRoutes = require('./routes/publicSettings');

// Create Express app
const app = express();
const port = config.port || 4000;

// Ensure uploads directories exist
const uploadsDir = path.join(__dirname, '../public/uploads');
const productImagesDir = path.join(uploadsDir, 'products');

if (!fs.existsSync(uploadsDir)) {
  fs.mkdirSync(uploadsDir, { recursive: true });
}

if (!fs.existsSync(productImagesDir)) {
  fs.mkdirSync(productImagesDir, { recursive: true });
}
const blogImagesDir = path.join(uploadsDir, 'blog');
if (!fs.existsSync(blogImagesDir)) {
  fs.mkdirSync(blogImagesDir, { recursive: true });
}

// Configure storage
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    // Determine destination based on upload type
    if (req.originalUrl.includes('/product')) {
      cb(null, productImagesDir);
    } else {
      cb(null, uploadsDir);
    }
  },
  filename: (req, file, cb) => {
    // Create unique filename with original extension
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
    const fileExt = path.extname(file.originalname);
    const safeName = path.basename(file.originalname, fileExt)
      .toLowerCase()
      .replace(/[^a-z0-9]/g, '-');
    
    cb(null, `${safeName}-${uniqueSuffix}${fileExt}`);
  }
});

// File filter to only allow images
const fileFilter = (req, file, cb) => {
  // Accept only image files
  if (file.mimetype.startsWith('image/')) {
    cb(null, true);
  } else {
    cb(new Error('Only image files are allowed!'), false);
  }
};

// Create the multer instance
const upload = multer({ 
  storage,
  fileFilter,
  limits: {
    fileSize: 5 * 1024 * 1024 // 5MB limit
  }
});

pool.connect()
  .then(async () => {
    console.log('Connected to PostgreSQL database');
    
    // Load settings from database
    try {
      const settings = await SystemSettings.getAllSettings(pool, query);
      if (settings) {
        // Update config with database settings
        config.updateFromDatabase(settings);
        console.log('Loaded settings from database');
      }
    } catch (error) {
      console.error('Error loading settings from database:', error);
    }
  })
  .catch(err => console.error('Database connection error:', err))
  .finally((() => {

    let timeInterval = 60 * 1000;
    if (config.environment === 'prod') {
      console.log('Setting up scheduled tasks for production environment, 10 mins');
      timeInterval = 10 * 60 * 1000;
    }else {
      console.log('Setting up scheduled tasks for development environment, 2 mins');
      timeInterval = 2 * 60 * 1000;
    }
    // Process stock notifications every X minutes
    setInterval(async () => {
      try {
        console.log('Processing low stock notifications...');
        const processedCount = await notificationService.processLowStockNotifications(pool, query);
        console.log(`Processed ${processedCount} low stock notifications`);
      } catch (error) {
        console.error('Error processing low stock notifications:', error);
      }
    }, timeInterval);
  }));
  
  
// Handle SSL proxy headers
app.use((req, res, next) => {
  // Trust X-Forwarded-Proto header from Cloudflare
  if (req.headers['x-forwarded-proto'] === 'https') {
    req.secure = true;
  }
  next();
});
app.set('trust proxy', true);
// Middleware
app.use(cors({
  origin: '*', 
  credentials: true
}));

app.use('/api/payment', stripePaymentRoutes(pool, query, authMiddleware(pool, query)));
app.use(express.json());
app.use(morgan('dev'));

// Serve static files - serve the entire public directory
app.use(express.static(path.join(__dirname, '../public')));

// More specific static file serving for images
app.use('/images', express.static(path.join(__dirname, '../public/uploads')));
app.use('/uploads', express.static(path.join(__dirname, '../public/uploads')));
app.use('/api/uploads', express.static(path.join(__dirname, '../public/uploads')));
app.use('/api/images', express.static(path.join(__dirname, '../public/uploads')));
app.use('/uploads/blog', express.static(path.join(__dirname, '../public/uploads/blog')));
app.use('/api/uploads/blog', express.static(path.join(__dirname, '../public/uploads/blog')));

if (!fs.existsSync(path.join(__dirname, '../public/uploads'))) {
  fs.mkdirSync(path.join(__dirname, '../public/uploads'), { recursive: true });
}

if (!fs.existsSync(path.join(__dirname, '../public/uploads/products'))) {
  fs.mkdirSync(path.join(__dirname, '../public/uploads/products'), { recursive: true });
}

// For direct access to product images
app.use('/products/images', express.static(path.join(__dirname, '../public/uploads/products')));
app.use('/api/products/images', express.static(path.join(__dirname, '../public/uploads/products')));
// Health check route
app.get('/health', (req, res) => {
  res.status(200).json({ status: 'ok', message: 'API is running' });
});

app.use('/api/settings', publicSettingsRoutes(pool, query));

// Upload endpoints
// Public upload endpoint (basic)
app.post('/api/image/upload', upload.single('image'), (req, res) => {
  console.log('/api/image/upload');
  if (!req.file) {
    return res.status(400).json({
      error: true,
      message: 'No image file provided'
    });
  }

  res.json({
    success: true,
    imagePath: `/uploads/${req.file.filename}`
  });
});

app.get('/api/public-file/:filename', (req, res) => {
  const { filename } = req.params;
  
  // Prevent path traversal attacks
  if (filename.includes('..') || filename.includes('/')) {
    return res.status(400).json({
      error: true,
      message: 'Invalid filename'
    });
  }
  
  // Serve files from public uploads folder
  res.sendFile(path.join(__dirname, '../public/uploads', filename));
});

app.use('/api/product-reviews', productReviewsRoutes(pool, query, authMiddleware(pool, query)));
app.use('/api/admin/product-reviews', productReviewsAdminRoutes(pool, query, adminAuthMiddleware(pool, query)));

app.use('/api/admin/users', usersAdminRoutes(pool, query, adminAuthMiddleware(pool, query)));
app.use('/api/admin/coupons', couponsAdminRoutes(pool, query, adminAuthMiddleware(pool, query)));
app.use('/api/admin/orders', ordersAdminRoutes(pool, query, adminAuthMiddleware(pool, query)));
app.use('/api/admin/blog', blogAdminRoutes(pool, query, adminAuthMiddleware(pool, query)));
app.use('/api/admin/blog-comments', blogCommentsAdminRoutes(pool, query, adminAuthMiddleware(pool, query)));
app.use('/api/admin/email-templates', emailTemplatesAdminRoutes(pool, query, adminAuthMiddleware(pool, query))); // Add new route

// Admin-only product image upload
app.post('/api/image/product', adminAuthMiddleware(pool, query), upload.single('image'), (req, res) => {
  console.log('/api/image/product', req.file);
  if (!req.file) {
    return res.status(400).json({
      error: true,
      message: 'No image file provided'
    });
  }

  // Get the relative path to the image
  const imagePath = `/uploads/products/${req.file.filename}`;

  res.json({
    success: true,
    imagePath,
    filename: req.file.filename
  });
});

// Upload multiple product images (admin only)
app.post('/api/image/products', adminAuthMiddleware(pool, query), upload.array('images', 10), (req, res) => {
  console.log('/api/image/products', req.files);
  if (!req.files || req.files.length === 0) {
    return res.status(400).json({
      error: true,
      message: 'No image files provided'
    });
  }

  // Get the relative paths to the images
  const imagePaths = req.files.map(file => ({
    imagePath: `/uploads/products/${file.filename}`,
    filename: file.filename
  }));

  res.json({
    success: true,
    images: imagePaths
  });
});

// Delete product image (admin only)
app.delete('/api/image/product/:filename', adminAuthMiddleware(pool, query), (req, res) => {
  try {
    const { filename } = req.params;
    
    // Prevent path traversal attacks
    if (filename.includes('..') || filename.includes('/')) {
      return res.status(400).json({
        error: true,
        message: 'Invalid filename'
      });
    }

    const filePath = path.join(__dirname, '../public/uploads/products', filename);

    // Check if file exists
    if (!fs.existsSync(filePath)) {
      return res.status(404).json({
        error: true,
        message: 'Image not found'
      });
    }

    // Delete the file
    fs.unlinkSync(filePath);

    res.json({
      success: true,
      message: 'Image deleted successfully'
    });
  } catch (error) {
    console.error('Error deleting image:', error);
    res.status(500).json({
      error: true,
      message: 'Failed to delete image'
    });
  }
});

// Use routes
app.use('/api/admin/settings', settingsAdminRoutes(pool, query, adminAuthMiddleware(pool, query)));
app.use('/api/products', productRoutes(pool, query));
app.use('/api/auth', authRoutes(pool, query));
app.use('/api/user/orders', userOrdersRoutes(pool, query, authMiddleware(pool, query)));

app.use('/api/blog', blogRoutes(pool, query, authMiddleware(pool, query)));
app.use('/api/cart', cartRoutes(pool, query, authMiddleware(pool, query)));
app.use('/api/admin/products', productAdminRoutes(pool, query, adminAuthMiddleware(pool, query)));
app.use('/api/admin/categories', categoryAdminRoutes(pool, query, adminAuthMiddleware(pool, query)));
app.use('/api/shipping', shippingRoutes(pool, query, authMiddleware(pool, query)));

// Error handling middleware
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({
    error: true,
    message: err.message || 'An unexpected error occurred'
  });
});

// Start server
app.listen(port, () => {
  console.log(`Server running on port ${port} in ${config.environment} environment`);
});

module.exports = app;