/**
 * Development server with same-origin API proxy.
 * Equivalent to Angular's proxy.conf.json + ng serve.
 *
 * Port 8080 (browser-facing):
 *   /api/*      → curl → https://flights.test.aeroflot.ru (bypasses WAF via curl TLS)
 *   /flights/*  → curl → https://flights.test.aeroflot.ru
 *   /*          → localhost:8081 (Modern.js SSR + HMR)
 */
import express from "express";
import { createProxyMiddleware } from "http-proxy-middleware";
import { execFile, spawn } from "node:child_process";
import { resolve } from "node:path";
import { existsSync } from "node:fs";

const PUBLIC_PORT = 8080;
const MODERNJS_PORT = 8081;
const API_TARGET = "https://flights.test.aeroflot.ru";

// --- Start Modern.js on internal port ---
console.log(`Starting Modern.js on :${MODERNJS_PORT}...`);

// Resolve the modern binary directly to avoid DEP0190 (shell: true with spawn)
const modernBin = resolve("node_modules", ".bin", "modern");
const modernProcess = existsSync(modernBin)
  ? spawn(modernBin, ["dev"], {
      stdio: "inherit",
      env: { ...process.env, PORT: String(MODERNJS_PORT) },
    })
  : spawn(process.execPath, [resolve("node_modules", "@modern-js/app-tools", "bin", "modern.js"), "dev"], {
      stdio: "inherit",
      env: { ...process.env, PORT: String(MODERNJS_PORT) },
    });
modernProcess.on("error", (err) => {
  console.error("Modern.js failed:", err);
  process.exit(1);
});

await new Promise((r) => setTimeout(r, 18000));

const app = express();

// --- Mock fallback for /api/appSettings when WAF blocks requests ---
app.get("/api/appSettings", (req, res) => {
  res.json({
    showDebugVersion: "False",
    uiOptions: {
      isTestVersion: "",
      filter: {
        schedule: { searchFrom: "30d", searchTo: "30d", timeStep: "" },
        onlineboard: { searchFrom: "2d", searchTo: "14d", timeStep: "" },
      },
      buttons: {
        buyTicket: { period: { min: "2h", max: "72h" } },
        flightStatus: { availableFrom: "24h", visible: "" },
      },
    },
  });
});

// --- API proxy via curl (bypasses WAF TLS fingerprinting) ---
app.use(["/api", "/flights"], (req, res) => {
  const targetUrl = `${API_TARGET}${req.originalUrl}`;

  // Use curl to make the request — it passes through the system proxy
  // with a proper TLS fingerprint that the WAF accepts.
  const args = [
    "-s",                                    // silent
    "-H", `Accept: ${req.headers.accept || "application/json"}`,
    "-H", `User-Agent: ${req.headers["user-agent"] || "Mozilla/5.0"}`,
    "-H", `Accept-Language: ${req.headers["accept-language"] || "ru"}`,
    "-w", "\n%{http_code}",                  // append status code at end
    targetUrl,
  ];

  if (req.method === "POST") {
    args.unshift("-X", "POST");
    // Read body and pass to curl
    let body = "";
    req.on("data", (chunk) => { body += chunk; });
    req.on("end", () => {
      if (body) {
        args.push("-d", body);
        args.push("-H", "Content-Type: application/json");
      }
      execCurl(args, res);
    });
  } else {
    execCurl(args, res);
  }
});

function execCurl(args, res) {
  execFile("/usr/bin/curl", args, { maxBuffer: 10 * 1024 * 1024, timeout: 30000 }, (err, stdout) => {
    if (err) {
      res.status(502).json({ error: err.message });
      return;
    }

    // stdout = body + "\n" + statusCode (from -w "\n%{http_code}")
    const lastNewline = stdout.lastIndexOf("\n");
    const body = lastNewline > 0 ? stdout.substring(0, lastNewline) : stdout;
    const statusStr = lastNewline > 0 ? stdout.substring(lastNewline + 1).trim() : "200";
    const status = parseInt(statusStr) || 200;

    const isJson = body.trimStart().startsWith("{") || body.trimStart().startsWith("[");

    res.status(status);
    res.set("Content-Type", isJson ? "application/json" : "text/html");
    res.set("Access-Control-Allow-Origin", "*");
    res.send(body);
  });
}

// --- Everything else → Modern.js ---
const modernProxy = createProxyMiddleware({
  target: `http://localhost:${MODERNJS_PORT}`,
  changeOrigin: false,
  ws: true,
  logLevel: "silent",
});
app.use(modernProxy);

const server = app.listen(PUBLIC_PORT, () => {
  console.log(`\n  ✓ Dev server: http://localhost:${PUBLIC_PORT}`);
  console.log(`    /api/*     → curl → ${API_TARGET}`);
  console.log(`    /*         → Modern.js :${MODERNJS_PORT}\n`);
});

// Forward WebSocket upgrades to Modern.js HMR server explicitly,
// preventing reconnection spam from http-proxy-middleware's built-in ws handling.
server.on("upgrade", modernProxy.upgrade);

process.on("SIGINT", () => { modernProcess.kill(); process.exit(); });
process.on("SIGTERM", () => { modernProcess.kill(); process.exit(); });
