const express = require('express');
const cors = require('cors');
const { spawn } = require('child_process');
const path = require('path');
const fs = require('fs');
const { corsMiddleware, corsErrorHandler } = require('./middleware/cors');
const { initPool } = require('./utils/db');
const productsRouter = require('./routes/products');
const dashboardRouter = require('./routes/dashboard');
const ordersRouter = require('./routes/orders');
const csvRouter = require('./routes/data-management');
const analyticsRouter = require('./routes/analytics');
const purchaseOrdersRouter = require('./routes/purchase-orders');
const configRouter = require('./routes/config');
const metricsRouter = require('./routes/metrics');
const importRouter = require('./routes/import');
const aiValidationRouter = require('./routes/ai-validation');
const aiRouter = require('./routes/ai');
const templatesRouter = require('./routes/templates');
const aiPromptsRouter = require('./routes/ai-prompts');
const reusableImagesRouter = require('./routes/reusable-images');
const categoriesAggregateRouter = require('./routes/categoriesAggregate');
const vendorsAggregateRouter = require('./routes/vendorsAggregate');
const brandsAggregateRouter = require('./routes/brandsAggregate');
const htsLookupRouter = require('./routes/hts-lookup');
const importSessionsRouter = require('./routes/import-sessions');
const newsletterRouter = require('./routes/newsletter');

// Get the absolute path to the .env file
const envPath = '/var/www/html/inventory/.env';
console.log('Looking for .env file at:', envPath);
console.log('.env file exists:', fs.existsSync(envPath));

try {
  require('dotenv').config({ path: envPath });
  console.log('.env file loaded successfully');
  console.log('Environment check:', {
    NODE_ENV: process.env.NODE_ENV || 'not set',
    PORT: process.env.PORT || 'not set',
    DB_HOST: process.env.DB_HOST || 'not set',
    DB_USER: process.env.DB_USER || 'not set',
    DB_NAME: process.env.DB_NAME || 'not set',
    DB_PASSWORD: process.env.DB_PASSWORD ? '[password set]' : 'not set',
    DB_PORT: process.env.DB_PORT || 'not set',
    DB_SSL: process.env.DB_SSL || 'not set'
  });
} catch (error) {
  console.error('Error loading .env file:', error);
}

// Resolve important directories relative to the project root
const serverRoot = path.resolve(__dirname, '..');
const configuredUploadsDir = process.env.UPLOADS_DIR;
const uploadsDir = configuredUploadsDir
  ? (path.isAbsolute(configuredUploadsDir)
      ? configuredUploadsDir
      : path.resolve(serverRoot, configuredUploadsDir))
  : path.resolve(serverRoot, 'uploads');

// Persist the resolved uploads directory so downstream modules share the same path
process.env.UPLOADS_DIR = uploadsDir;

const requiredDirs = [path.resolve(serverRoot, 'logs'), uploadsDir];

requiredDirs.forEach(dir => {
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true });
  }
});

const app = express();

// Debug middleware to log request details
app.use((req, res, next) => {
  console.log('Request details:', {
    method: req.method,
    url: req.url,
    origin: req.get('Origin'),
    headers: req.headers
  });
  next();
});

// Apply CORS middleware first, before any other middleware
app.use(corsMiddleware);

// Body parser middleware
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true, limit: '10mb' }));

// Initialize database pool and start server
async function startServer() {
  try {
    // Initialize database pool
    const pool = await initPool({
      host: process.env.DB_HOST,
      user: process.env.DB_USER,
      password: process.env.DB_PASSWORD,
      database: process.env.DB_NAME,
      port: process.env.DB_PORT || 5432,
      max: process.env.NODE_ENV === 'production' ? 20 : 10,
      idleTimeoutMillis: 30000,
      connectionTimeoutMillis: 2000,
      ssl: process.env.DB_SSL === 'true' ? {
        rejectUnauthorized: false
      } : false
    });

    // Make pool available to routes
    app.locals.pool = pool;

    // Set up routes after pool is initialized
    app.use('/api/products', productsRouter);
    app.use('/api/dashboard', dashboardRouter);
    app.use('/api/orders', ordersRouter);
    app.use('/api/csv', csvRouter);
    app.use('/api/analytics', analyticsRouter);
    app.use('/api/purchase-orders', purchaseOrdersRouter);
    app.use('/api/config', configRouter);
    app.use('/api/metrics', metricsRouter);
    // Use only the aggregate routes for vendors and categories
    app.use('/api/vendors', vendorsAggregateRouter); 
    app.use('/api/categories', categoriesAggregateRouter);
    // Keep the aggregate-specific endpoints for backward compatibility
    app.use('/api/categories-aggregate', categoriesAggregateRouter);
    app.use('/api/vendors-aggregate', vendorsAggregateRouter);
    app.use('/api/brands-aggregate', brandsAggregateRouter);
    app.use('/api/import', importRouter);
    app.use('/api/ai-validation', aiValidationRouter);
    app.use('/api/ai', aiRouter);
    app.use('/api/templates', templatesRouter);
    app.use('/api/ai-prompts', aiPromptsRouter);
    app.use('/api/reusable-images', reusableImagesRouter);
    app.use('/api/hts-lookup', htsLookupRouter);
    app.use('/api/import-sessions', importSessionsRouter);
    app.use('/api/newsletter', newsletterRouter);

    // Basic health check route
    app.get('/health', (req, res) => {
      res.json({ 
        status: 'ok',
        timestamp: new Date().toISOString(),
        environment: process.env.NODE_ENV
      });
    });

    // CORS error handler - must be before other error handlers
    app.use(corsErrorHandler);

    // Error handling middleware - MUST be after routes and CORS error handler
    app.use((err, req, res, next) => {
      console.error(`[${new Date().toISOString()}] Error:`, err);
      
      // Send detailed error in development, generic in production
      const error = process.env.NODE_ENV === 'production'
        ? 'An internal server error occurred'
        : err.message || err;
        
      res.status(err.status || 500).json({ error });
    });

    const PORT = process.env.PORT || 3000;
    app.listen(PORT, () => {
      console.log(`[Server] Running in ${process.env.NODE_ENV || 'development'} mode on port ${PORT}`);
    });
  } catch (error) {
    console.error('Failed to start server:', error);
    process.exit(1);
  }
}

// Handle uncaught exceptions
process.on('uncaughtException', (err) => {
  console.error(`[${new Date().toISOString()}] Uncaught Exception:`, err);
  process.exit(1);
});

process.on('unhandledRejection', (reason, promise) => {
  console.error(`[${new Date().toISOString()}] Unhandled Rejection at:`, promise, 'reason:', reason);
});

// Initialize client sets for SSE
const importClients = new Set();
const updateClients = new Set();
const resetClients = new Set();
const resetMetricsClients = new Set();

// Helper function to send progress to SSE clients
const sendProgressToClients = (clients, data) => {
  clients.forEach(client => {
    try {
      client.write(`data: ${JSON.stringify(data)}\n\n`);
    } catch (error) {
      console.error('Error sending SSE update:', error);
    }
  });
};

// Setup SSE connection
const setupSSE = (req, res) => {
  const { type } = req.params;
  
  // Set headers for SSE
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive',
    'Access-Control-Allow-Origin': req.headers.origin || '*',
    'Access-Control-Allow-Credentials': 'true'
  });

  // Send initial message
  res.write('data: {"status":"connected"}\n\n');

  // Add client to appropriate set
  const clientSet = type === 'import' ? importClients :
                   type === 'update' ? updateClients :
                   type === 'reset' ? resetClients :
                   type === 'reset-metrics' ? resetMetricsClients :
                   null;

  if (clientSet) {
    clientSet.add(res);
    
    // Remove client when connection closes
    req.on('close', () => {
      clientSet.delete(res);
    });
  }
};

// Start the server
startServer(); 
