import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { spawnSync } from "node:child_process";
import test from "node:test";

const ROOT = path.resolve(import.meta.dirname, "../..");
const ENTRYPOINT = path.join(ROOT, "entrypoint.sh");

function writeExecutable(filePath, contents) {
  fs.writeFileSync(filePath, contents, { mode: 0o755 });
}

test("entrypoint bypasses configured source CIDRs before TProxy interception", () => {
  const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "vpn-entrypoint-"));
  const commandLog = path.join(tmp, "commands.log");

  writeExecutable(
    path.join(tmp, "iptables"),
    `#!/usr/bin/env bash
printf 'iptables %s\\n' "$*" >> "$COMMAND_LOG"
exit 0
`,
  );
  writeExecutable(
    path.join(tmp, "ip"),
    `#!/usr/bin/env bash
printf 'ip %s\\n' "$*" >> "$COMMAND_LOG"
exit 0
`,
  );
  writeExecutable(
    path.join(tmp, "ipset"),
    `#!/usr/bin/env bash
printf 'ipset %s\\n' "$*" >> "$COMMAND_LOG"
exit 0
`,
  );
  writeExecutable(
    path.join(tmp, "sysctl"),
    `#!/usr/bin/env bash
printf 'sysctl %s\\n' "$*" >> "$COMMAND_LOG"
exit 0
`,
  );
  writeExecutable(
    path.join(tmp, "node"),
    `#!/usr/bin/env bash
printf 'node %s\\n' "$*" >> "$COMMAND_LOG"
exit 0
`,
  );

  const result = spawnSync("bash", [ENTRYPOINT], {
    cwd: ROOT,
    env: {
      ...process.env,
      PATH: `${tmp}${path.delimiter}${process.env.PATH}`,
      COMMAND_LOG: commandLog,
      TPROXY_BYPASS_SOURCE_CIDRS: "192.168.50.25/32 192.168.50.26/32",
      DIRECT_BYPASS_CACHE: "true",
      BYPASS_CIDRS: "10.0.0.0/8",
    },
    encoding: "utf8",
  });

  assert.equal(result.status, 0, result.stderr || result.stdout);

  const commands = fs.readFileSync(commandLog, "utf8").trim().split("\n");
  const sourceBypassIndex = commands.findIndex((line) =>
    line.includes(
      "iptables -w -t mangle -A VPN_PROXY_SRC_BYPASS -s 192.168.50.25/32 -j ACCEPT",
    ),
  );
  const secondSourceBypassIndex = commands.findIndex((line) =>
    line.includes(
      "iptables -w -t mangle -A VPN_PROXY_SRC_BYPASS -s 192.168.50.26/32 -j ACCEPT",
    ),
  );
  const sourceBypassJumpIndex = commands.findIndex((line) =>
    line.includes(
      "iptables -w -t mangle -A VPN_PROXY_TPROXY -j VPN_PROXY_SRC_BYPASS",
    ),
  );
  const directCacheIndex = commands.findIndex((line) =>
    line.includes("-m set --match-set vpn_direct_bypass dst -j RETURN"),
  );
  const tproxyIndex = commands.findIndex((line) =>
    line.includes("-p tcp -j TPROXY --on-port 7895"),
  );
  const ipForwardIndex = commands.findIndex((line) =>
    line.includes("sysctl -w net.ipv4.ip_forward=1"),
  );
  const forwardAcceptIndex = commands.findIndex((line) =>
    line.includes(
      "iptables -w -A VPN_PROXY_FWD_BYPASS -s 192.168.50.25/32 -j ACCEPT",
    ),
  );
  const forwardReturnIndex = commands.findIndex((line) =>
    line.includes(
      "iptables -w -A VPN_PROXY_FWD_BYPASS -d 192.168.50.25/32 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT",
    ),
  );
  const natMasqueradeIndex = commands.findIndex((line) =>
    line.includes(
      "iptables -w -t nat -A VPN_PROXY_NAT_BYPASS -s 192.168.50.25/32 -j MASQUERADE",
    ),
  );

  assert.notEqual(sourceBypassIndex, -1);
  assert.notEqual(secondSourceBypassIndex, -1);
  assert.notEqual(sourceBypassJumpIndex, -1);
  assert.notEqual(directCacheIndex, -1);
  assert.notEqual(tproxyIndex, -1);
  assert.notEqual(ipForwardIndex, -1);
  assert.notEqual(forwardAcceptIndex, -1);
  assert.notEqual(forwardReturnIndex, -1);
  assert.notEqual(natMasqueradeIndex, -1);
  assert.ok(sourceBypassJumpIndex < directCacheIndex);
  assert.ok(sourceBypassJumpIndex < tproxyIndex);
});
