import express, { type Request, Response, NextFunction } from "express";
import compression from "compression";
import session from "express-session";
import MemoryStore from "memorystore";
import { registerRoutes } from "./routes.js";
import { deploymentChecker } from "./deployment-checks.js";
import { errorHandler } from "./error-handlers.js";
import { setupEmailRoutes } from "./email-routes.js";
import { storage } from "./storage.js";
import path from "path";

const app = express();

// PERFORMANCE OPTIMIZATION: Enable gzip compression
app.use(compression({
  level: 6, // Good balance between compression and speed
  threshold: 1024, // Only compress files larger than 1KB
  filter: (req, res) => {
    // Compress everything except already compressed formats
    if (req.headers['x-no-compression']) {
      return false;
    }
    return compression.filter(req, res);
  }
}));

// Session configuration with MemoryStore
const MemStore = MemoryStore(session);
app.use(session({
  secret: process.env.SESSION_SECRET || 'locallendables_secret_key_2024',
  store: new MemStore({
    checkPeriod: 86400000 // prune expired entries every 24h
  }),
  resave: false,
  saveUninitialized: false,
  cookie: {
    secure: false, // Disable secure for Replit environment
    httpOnly: true,
    maxAge: 24 * 60 * 60 * 1000 // 24 hours
  }
}));

app.use(express.json());
app.use(express.urlencoded({ extended: false }));

// Add CORS and security headers for Replit environment
app.use((req: any, res: any, next: any) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
  res.header('X-Frame-Options', 'SAMEORIGIN');
  res.header('X-Content-Type-Options', 'nosniff');
  res.header('Cache-Control', 'no-cache, no-store, must-revalidate');
  res.header('Pragma', 'no-cache');
  res.header('Expires', '0');
  next();
});



// PERFORMANCE OPTIMIZATION: Serve static files with smart caching
const publicPath = path.resolve(import.meta.dirname, "..", "public");
app.use(express.static(publicPath, {
  setHeaders: (res: any, filePath: any) => {
    // Smart caching based on file type
    if (filePath.match(/\.(css|js|woff|woff2|ttf|eot)$/)) {
      // Cache CSS, JS, and fonts for 1 hour
      res.set({
        'Cache-Control': 'public, max-age=3600',
        'ETag': Date.now().toString()
      });
    } else if (filePath.match(/\.(jpg|jpeg|png|gif|svg|webp)$/)) {
      // Cache images for 30 minutes but allow lazy loading
      res.set({
        'Cache-Control': 'public, max-age=1800',
        'ETag': Date.now().toString()
      });
    } else {
      // No cache for HTML and other files to ensure fresh content
      res.set({
        'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0',
        'Pragma': 'no-cache',
        'Expires': '0'
      });
    }
  }
}));
app.use('/manifest.json', express.static(path.join(publicPath, 'manifest.json')));
app.use('/sw.js', express.static(path.join(publicPath, 'sw.js')));

// Cache-busting middleware for HTML responses only
app.use((req: any, res: any, next: any) => {
  // Block Vite/React requests
  if (req.path.includes('react') || req.path.includes('jsx') || req.path.includes('tsx') || 
      req.path.includes('@vite') || req.path.includes('client') || req.path.includes('src') ||
      req.path.includes('/@fs/') || req.path.includes('__vite') || req.path.includes('node_modules')) {
    return res.status(404).send('No React components - Express SSR only');
  }
  
  // Only apply aggressive cache-busting to HTML responses, not static assets
  if (!req.path.includes('.') || req.path.endsWith('.html')) {
    const cacheVersion = Date.now();
    res.set({
      'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0, private',
      'Pragma': 'no-cache',
      'Expires': '0',
      'Last-Modified': new Date().toUTCString(),
      'ETag': `"v${cacheVersion}"`,
      'Vary': 'Cache-Control'
    });
  }
  
  // Log forwarded requests but allow them (Replit needs these headers)
  if (req.headers['x-forwarded-proto'] || req.headers['x-forwarded-host']) {
    console.log('Forwarded request from Replit webview:', req.url);
  }
  
  next();
});

app.use((req: any, res: any, next: any) => {
  const start = Date.now();
  const path = req.path;
  let capturedJsonResponse: Record<string, any> | undefined = undefined;

  const originalResJson = res.json;
  res.json = function (bodyJson: any, ...args: any[]) {
    capturedJsonResponse = bodyJson;
    return originalResJson.apply(res, [bodyJson, ...args]);
  };

  res.on("finish", () => {
    const duration = Date.now() - start;
    
    // Log all 404s and errors for debugging back button issues
    if (res.statusCode >= 400) {
      console.error('ERROR:', req.method, path, res.statusCode, 'in', duration + 'ms -', req.headers['user-agent'] || 'Unknown');
    }
    
    if (path.startsWith("/api")) {
      let logLine = req.method + ' ' + path + ' ' + res.statusCode + ' in ' + duration + 'ms';
      if (capturedJsonResponse) {
        logLine += ' :: ' + JSON.stringify(capturedJsonResponse);
      }

      if (logLine.length > 80) {
        logLine = logLine.slice(0, 79) + "…";
      }

      console.log(logLine);
    }
  });

  next();
});

// Health check will be registered in routes.ts before catch-all handlers

(async () => {
  // Override SendGrid API key with correct value
  process.env.SENDGRID_API_KEY = "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";
  console.log(`✓ SendGrid API key updated: ${process.env.SENDGRID_API_KEY.substring(0, 10)}...`);

  // Register all application routes BEFORE error handling
  const server = await registerRoutes(app);

  // Initialize email notification system
  const emailScheduler = setupEmailRoutes(app, storage);

  // Error handling middleware (must be last)
  app.use((err: any, _req: Request, res: Response, _next: NextFunction) => {
    const status = err.status || err.statusCode || 500;
    const message = err.message || "Internal Server Error";
    console.error('Server error:', err);
    res.status(status).send(message);
  });

  // Initialize deployment compatibility checks and error handlers
  errorHandler.setupGlobalErrorHandlers();
  await deploymentChecker.initialize();
  
  // Start pure Express server - NO VITE, NO REACT  
  const port = deploymentChecker.getPort();
  const host = '0.0.0.0';
  
  // Ensure Replit webview connects to our Express server
  process.env.REPLIT_DEV_DOMAIN = `${host}:${port}`;
  
  server.listen(port, host, () => {
    console.log(`LocalLendables v0.88 Express SSR server running on ${host}:${port}`);
    console.log(`Access at: http://localhost:${port}`);
    console.log(`Demo users available - click any avatar on homepage`);
    console.log(`STABLE MODE: File watching disabled to prevent auto-restarts`);
  }).on('error', (err) => {
    console.error('Server failed to start:', err);
    process.exit(1);
  });

  // Disable file watching and auto-restart behavior
  process.on('SIGTERM', () => {
    console.log('SIGTERM received, server staying stable...');
  });

  process.on('SIGINT', () => {
    console.log('SIGINT received, server staying stable...');
  });

  // Prevent tsx watcher from restarting on file changes
  if (process.env.NODE_ENV === 'development') {
    console.log('Development mode: File watching suppressed for stability');
  }
})();
