// server.js
import express from "express";
import { createServer } from "http";
import { fileURLToPath } from "url";
import { dirname, join } from "path";
import fs from "fs";
import cors from "cors";
import dotenv from "dotenv";
import axios from "axios"; 
import { JSDOM } from "jsdom";


dotenv.config();

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const app = express();
const PORT = process.env.PORT || 3000;

app.use(cors());
// Increase limit for large HTML payloads
app.use(express.json({ limit: "10mb" }));

/* ----------  Shim for DOMParser  ---------- */
global.DOMParser = new JSDOM("").window.DOMParser;

/* ----------  Logging  ---------- */
app.use((req, _res, next) => {
  console.log(`[EXPRESS] ${req.method} ${req.url}`);
  next();
});

// Simple in-memory cache
const proxyCache = new Map();
const CACHE_TTL = 1000 * 60 * 60 * 24; // 24 hours

/* ----------  /api/proxy (REST API - No Puppeteer)  ---------- */
app.get("/api/proxy", async (req, res, next) => {
  try {
    const rawUrl = req.query.url;
    if (!rawUrl || typeof rawUrl !== "string") {
      return res.status(400).json({ error: "Missing url parameter" });
    }

    const targetUrl = rawUrl;
    const cacheKey = `proxy:${targetUrl}`;

    // 1. Check Cache
    if (proxyCache.has(cacheKey)) {
      const cached = proxyCache.get(cacheKey);
      if (Date.now() - cached.timestamp < CACHE_TTL) {
        console.log("[PROXY] Cache hit:", targetUrl);
        res.set("Content-Type", "text/html");
        return res.send(cached.html);
      }
    }

    console.log(`[PROXY] Sending to Browserless REST API: ${targetUrl}`);

    // 2. Prepare Browserless Request
    const browserlessEndpoint = `https://chrome.browserless.io/content?token=${process.env.BROWSERLESS_API_KEY}`;

    const payload = {
      url: targetUrl,
      // "waitFor" was causing the 400 error. We removed it.
      // We rely on "gotoOptions.waitUntil" below to handle loading.
      
      rejectResourceTypes: ["image", "media", "font"], // Save bandwidth
      gotoOptions: {
        waitUntil: "networkidle2", // Wait until network connections settle (page loaded)
        timeout: 30000 // 30s timeout for the page load
      },
      // Rotate User Agent to avoid bot detection
      setExtraHTTPHeaders: {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
        "Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8"
      }
    };

    // 3. Send Request via Axios
    const response = await axios.post(browserlessEndpoint, payload, {
      headers: { 
        'Content-Type': 'application/json',
        'Cache-Control': 'no-cache' 
      },
      responseType: 'text', // We want the HTML string
      timeout: 45000 // 45s total timeout for the axios call
    });

    const html = response.data;

    // 4. Update Cache
    proxyCache.set(cacheKey, { html, timestamp: Date.now() });
    
    // Cleanup cache if too big
    if (proxyCache.size > 500) {
      const firstKey = proxyCache.keys().next().value;
      proxyCache.delete(firstKey);
    }

    // 5. Respond to Client
    res.set("Content-Type", "text/html");
    res.send(html);

  } catch (err) {
    console.error("[PROXY] Error calling Browserless:");
    
    if (err.response) {
        // Browserless API returned an error (401, 400, 500, etc.)
        console.error(`Status: ${err.response.status}`);
        console.error(`Data: ${typeof err.response.data === 'object' ? JSON.stringify(err.response.data) : err.response.data}`);
        
        if (err.response.status === 401) {
             console.error("❌ ERROR: Invalid BROWSERLESS_API_KEY in .env");
        }
        return res.status(err.response.status).send(err.response.data);
    } 
    
    // Network error or other issue
    console.error(err.message);
    next(err);
  }
});



/* ----------  SPA Catch-all  ---------- */
const DIST_DIR = join(__dirname, "dist");
const INDEX_PATH = join(DIST_DIR, "index.html");

if (fs.existsSync(DIST_DIR) && fs.existsSync(INDEX_PATH)) {
  app.use(express.static(DIST_DIR));
  app.get(/^\/.*$/, (_req, res) => res.sendFile(INDEX_PATH));
} else {
  console.warn("WARNING: dist/ folder missing. Static files not served.");
}

/* ----------  Global Error Handler  ---------- */
app.use((err, _req, res, _next) => {
  console.error("[EXPRESS ERROR]", err.message);
  if (!res.headersSent) {
    res.status(500).json({ ok: false, error: "Server error" });
  }
});

/* ----------  Start Server  ---------- */
const server = createServer(app);
server.listen(PORT, "0.0.0.0", () => {
  console.log(`\n--- Server running on :${PORT} ---`);
  
  // Debug key presence (safe log)
  const key = process.env.BROWSERLESS_API_KEY;
  if (key && key !== "XXXxxxXXX") {
    console.log(`Browserless Key: Present (${key.substring(0,4)}...)`);
  } else {
    console.error(`❌ Browserless Key: MISSING or Placeholder in .env`);
  }
  
  console.log(`Proxy: /api/proxy (Axios + Browserless REST)`);
  console.log(`----------------------------------\n`);
});

server.on("error", (e) => console.error("Server error:", e));