import { generateNativeConf } from "./wireguard-config.js"
import { getTrafficFlowSettingsRow, listHostPeers } from "./traffic-flow-settings.js"
import type { TrafficFlowHostFile } from "@mmapp/contracts/traffic-flow"

const COMPOSE_DIR = "/opt/cdn-mm"

export function buildHostWgQuickConf(): string {
  const row = getTrafficFlowSettingsRow()
  const peers = listHostPeers()
  return generateNativeConf({
    name: "wg-flow",
    mtu: 1420,
    privateKey: row.hostPrivateKey || undefined,
    address: `${row.collectorIp}/24`,
    comment: "MikrotikManager traffic-flow collector",
    peers: peers.map((p) => ({
      publicKey: p.publicKey,
      allowedIps: p.allowedIps,
      comment: p.name,
      endpoint: p.endpoint,
      persistentKeepalive: p.endpoint ? 25 : undefined,
    })),
  })
}

export function buildHostComposeOverride(): string {
  const row = getTrafficFlowSettingsRow()
  return [
    "# Docker Compose merge для /opt/cdn-mm",
    "# Не править docker-compose.yml. Traefik не трогать.",
    "# Сначала: wg-quick up wg-flow  (адрес " + row.collectorIp + ")",
    "# затем: docker compose up -d --force-recreate backend",
    "# Docker userland-proxy может SNAT UDP source в 172.x — ingest сопоставит единственный JH.",
    "",
    "services:",
    "  backend:",
    "    environment:",
    "      FLOW_LISTEN_HOST: \"0.0.0.0\"",
    "    ports:",
    `      - "${row.collectorIp}:${row.flowListenPort}:${row.flowListenPort}/udp"`,
    "",
  ].join("\n")
}

export function buildHostLinuxInstallSh(): string {
  const row = getTrafficFlowSettingsRow()
  const conf = buildHostWgQuickConf().replace(/\s+$/, "") + "\n"
  const override = buildHostComposeOverride()
  const collector = row.collectorIp
  const flowPort = row.flowListenPort

  return `#!/usr/bin/env bash
# WG-клиент на хосте /opt/cdn-mm → JH:13232, IPFIX в контейнер backend.
# Запуск: sudo bash install-wg-flow.sh
set -euo pipefail

if [[ \${EUID:-$(id -u)} -ne 0 ]]; then
  echo "Запустите от root: sudo bash $0" >&2
  exit 1
fi

COLLECTOR_IP="${collector}"
FLOW_PORT="${flowPort}"
COMPOSE_DIR="${COMPOSE_DIR}"

if ! command -v wg >/dev/null 2>&1; then
  apt-get update
  DEBIAN_FRONTEND=noninteractive apt-get install -y wireguard
fi

install -d -m 700 /etc/wireguard
cat > /etc/wireguard/wg-flow.conf <<'WGEOF'
${conf}WGEOF
chmod 600 /etc/wireguard/wg-flow.conf

systemctl enable --now wg-quick@wg-flow
echo "=== wg show wg-flow ==="
wg show wg-flow
echo "=== адрес (ожидаем \${COLLECTOR_IP}/24) ==="
ip -4 addr show dev wg-flow

if [[ ! -d "\$COMPOSE_DIR" ]]; then
  echo "Нет \$COMPOSE_DIR — положите override.yml туда вручную (вкладка compose)." >&2
  exit 1
fi

cat > "\$COMPOSE_DIR/docker-compose.override.yml" <<'OVEOF'
${override}OVEOF

cd "\$COMPOSE_DIR"
docker compose up -d --force-recreate backend

echo "=== UDP \${FLOW_PORT} на хосте (ожидаем \${COLLECTOR_IP}:\${FLOW_PORT} docker-proxy) ==="
ss -ulnp | grep -E "\${FLOW_PORT}" || true
echo "=== PortBindings mmapp-backend ==="
docker inspect -f '{{json .HostConfig.PortBindings}}' mmapp-backend
echo "=== handshake (keepalive 25s к JH:13232) ==="
wg show wg-flow

# nft на хосте MM не трогаем. Bind только на COLLECTOR_IP, не 0.0.0.0.
# Если backend стартовал до wg-flow: docker compose up -d --force-recreate backend

echo "Готово. Traefik не трогали. UDP \${FLOW_PORT} только на \${COLLECTOR_IP}, не на 0.0.0.0."
`
}

export function listTrafficFlowHostFiles(): TrafficFlowHostFile[] {
  return [
    { id: "linux", label: "Linux", filename: "install-wg-flow.sh", code: buildHostLinuxInstallSh() },
    { id: "wg-quick", label: "wg-flow.conf", filename: "wg-flow.conf", code: buildHostWgQuickConf() },
    { id: "compose", label: "compose", filename: "docker-compose.override.yml", code: buildHostComposeOverride() },
  ]
}
