const fetch = require('node-fetch');
const express = require('express');
const cors = require('cors');
const dotenv = require('dotenv');
const rateLimit = require('express-rate-limit');

dotenv.config();

const app = express();

// Trust proxy - required for Vercel
app.set('trust proxy', 1);

const port = process.env.PORT || 3000;

// Security and configuration settings
const RATE_LIMIT_WINDOW_MS = parseInt(process.env.RATE_LIMIT_WINDOW_MS || '900000', 10); // 15 minutes default
const RATE_LIMIT_MAX = parseInt(process.env.RATE_LIMIT_MAX || '100', 10); // 100 requests per window default
const REQUEST_TIMEOUT_MS = parseInt(process.env.REQUEST_TIMEOUT_MS || '120000', 10); // 120 seconds default (2 minutes)
const API_TOKEN = process.env.API_TOKEN; // Optional API token for additional security

// Parse FRONTEND_URL into array of allowed origins
// Parse FRONTEND_URL into array of allowed origins
const allowedOrigins = process.env.FRONTEND_URL ? 
  process.env.FRONTEND_URL.split(',').map(origin => origin.trim()) :
  [
    'https://360.articulate.com', 
    'https://articulateusercontent.com',
    'https://vlc-git-main-an802adams-projects.vercel.app'
  ];

// Add Google Cloud Storage domains if not already included
const googleStorageDomains = [
  'https://storage.googleapis.com',
  'https://storage.cloud.google.com',
  'https://elearning-demo-an802adam.storage.googleapis.com'
];

// Add Google domains if not already in allowedOrigins
googleStorageDomains.forEach(domain => {
  if (!allowedOrigins.includes(domain)) {
    allowedOrigins.push(domain);
  }
});

// Add development origins if not in production
if (process.env.NODE_ENV !== 'production') {
  allowedOrigins.push(
    'null',  // Allow file:// protocol
    'http://localhost',
    'http://localhost:3000',
    'http://127.0.0.1',
    'http://127.0.0.1:3000'
  );
}

// Rate limiting configuration
const limiter = rateLimit({
  windowMs: RATE_LIMIT_WINDOW_MS,
  max: RATE_LIMIT_MAX,
  message: 'Too many requests from this IP, please try again later.',
  standardHeaders: true,
  legacyHeaders: false,
  // Vercel-specific IP handling
  keyGenerator: (req) => {
    return req.ip; // This will now correctly get the IP from Vercel's proxy
  }
});

// CORS configuration - DISABLED FOR TESTING
// const corsOptions = {
//   origin: function (origin, callback) {
//     // For local file:// protocol, origin will be null
//     // Also allow requests with no origin (like mobile apps or curl requests)
//     if (!origin || allowedOrigins.includes(origin) || 
//         // Allow any Google Cloud Storage subdomains
//         origin?.endsWith('.storage.googleapis.com') ||
//         origin?.endsWith('.cloud.google.com')) {
//       callback(null, true);
//     } else {
//       console.log(`Rejected Origin: ${origin}`);
//       callback(new Error('Not allowed by CORS'));
//     }
//   },
//   methods: ['GET', 'POST', 'OPTIONS'],
//   allowedHeaders: ['Content-Type', 'Authorization'],
//   credentials: true,
//   optionsSuccessStatus: 204
// };

// Middleware - CORS DISABLED FOR TESTING
app.use(cors()); // Allow all origins for testing
app.use(express.json());
app.use(limiter);

// Optional API token validation middleware
const validateApiToken = (req, res, next) => {
  if (!API_TOKEN) {
    return next();
  }

  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ') || authHeader.split(' ')[1] !== API_TOKEN) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  next();
};

// Health check endpoint
app.get('/health', (req, res) => {
  res.json({ status: 'ok', timestamp: new Date().toISOString() });
});

// Route for handling Storyline requests
app.post('/storyline', validateApiToken, async (req, res) => {
  const { webhookId, ...rest } = req.body;

  console.log(`Received webhookId: ${webhookId}, with data:`, JSON.stringify(rest));

  try {
    const makeWebhookUrl = `https://hook.us1.make.com/${webhookId}`;
    
    // Set up timeout for the Make webhook request
    const controller = new AbortController();
    const timeout = setTimeout(() => {
      controller.abort();
    }, REQUEST_TIMEOUT_MS);

    try {
      const makeResponse = await fetch(makeWebhookUrl, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(rest),
        signal: controller.signal
      });

      clearTimeout(timeout);

      const contentType = makeResponse.headers.get('content-type');
      let makeData;

      if (contentType && contentType.includes('application/json')) {
        makeData = await makeResponse.json();
      } else {
        makeData = await makeResponse.text();
        try {
          makeData = JSON.parse(makeData);
        } catch (e) {
          console.log('Response was not valid JSON, returning as is');
        }
      }

      
      if (!makeResponse.ok) {
        throw new Error(`Make webhook error: ${makeResponse.statusText}`);
      }

      res.json(makeData);
      console.log(`Success - Data sent to Storyline:`, JSON.stringify(makeData));
    } catch (error) {
      if (error.name === 'AbortError') {
        throw new Error(`Request timeout after ${REQUEST_TIMEOUT_MS}ms`);
      }
      throw error;
    }
  } catch (error) {
    console.error('Error communicating with Make:', error);
    res.status(500).json({ 
      error: 'Error communicating with Make',
      message: error.message
    });
  }
});

// Error handling middleware
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({
    error: 'Internal Server Error',
    message: process.env.NODE_ENV === 'development' ? err.message : 'An unexpected error occurred'
  });
});

app.listen(port, () => {
  console.log(`Middleware server listening on port ${port}`);
  console.log(`Allowed origins: ${allowedOrigins.join(', ')}`);
  console.log(`Rate limit: ${RATE_LIMIT_MAX} requests per ${RATE_LIMIT_WINDOW_MS}ms`);
  console.log(`Request timeout: ${REQUEST_TIMEOUT_MS}ms`);
  console.log(`API token protection: ${API_TOKEN ? 'Enabled' : 'Disabled'}`);
});
