#!/usr/bin/env node
import { spawnSync } from "node:child_process";
import "dotenv/config";

const args = process.argv.slice(2);

function getArg(name) {
  const index = args.indexOf(name);
  return index >= 0 ? args[index + 1] : undefined;
}

function hasFlag(name) {
  return args.includes(name);
}

function usage() {
  console.log(`Usage:
  node scripts/provision-mqtt-device.mjs --device-id <device-id> [--base-url http://127.0.0.1:3000] [--apply-local]

Options:
  --device-id     Device UUID from the platform.
  --base-url      Running backend URL. Default: BASE_URL env or http://127.0.0.1:3000.
  --apply-local   Run mosquitto_passwd locally. Use only on the broker host.

Environment:
  ADMIN_TOKEN     Admin bearer token. Default: admin-dev-token.
  MOSQUITTO_PASSWD_FILE  Default: /etc/mosquitto/passwd.
  MOSQUITTO_ACL_FILE     Default: /etc/mosquitto/acl.
`);
}

const deviceId = getArg("--device-id");
const baseUrl = getArg("--base-url") || process.env.BASE_URL || "http://127.0.0.1:3000";
const adminToken = process.env.ADMIN_TOKEN || "admin-dev-token";
const passwdFile = process.env.MOSQUITTO_PASSWD_FILE || "/etc/mosquitto/passwd";
const aclFile = process.env.MOSQUITTO_ACL_FILE || "/etc/mosquitto/acl";
const applyLocal = hasFlag("--apply-local");

if (!deviceId || hasFlag("--help") || hasFlag("-h")) {
  usage();
  process.exit(deviceId ? 0 : 1);
}

function shellQuote(value) {
  return `'${String(value).replace(/'/g, "'\\''")}'`;
}

async function rotateCredential() {
  const response = await fetch(`${baseUrl}/admin/devices/${deviceId}/credentials/rotate`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${adminToken}`,
      "Content-Type": "application/json"
    },
    body: "{}"
  });

  const payload = await response.json().catch(() => ({}));
  if (!response.ok) {
    throw new Error(payload?.message || payload?.code || `rotate failed with status ${response.status}`);
  }

  return payload.data;
}

function applyMosquittoPassword(username, password) {
  const result = spawnSync("sudo", ["mosquitto_passwd", "-b", passwdFile, username, password], {
    stdio: "inherit"
  });
  if (result.status !== 0) {
    throw new Error(`mosquitto_passwd failed with status ${result.status}`);
  }
}

const data = await rotateCredential();
const username = data.credential.mqtt_username;
const password = data.credential.mqtt_password;

if (applyLocal) {
  applyMosquittoPassword(username, password);
}

console.log(
  JSON.stringify(
    {
      device_id: data.device.id,
      mqtt_username: username,
      mqtt_password: password,
      one_time_secret: true,
      applied_local: applyLocal,
      mosquitto_commands: [
        `sudo mosquitto_passwd -b ${shellQuote(passwdFile)} ${shellQuote(username)} ${shellQuote(password)}`,
        `node scripts/check-mqtt-acl.mjs --file ${shellQuote(aclFile)} || node scripts/check-mqtt-acl.mjs --print-template`,
        "sudo chown root:mosquitto /etc/mosquitto/passwd",
        "sudo chmod 640 /etc/mosquitto/passwd",
        "sudo systemctl reload mosquitto"
      ],
      topic_scope: [
        `device publish/readwrite: devices/${username}/uplink/#`,
        `device subscribe/read: devices/${username}/downlink/#`,
        "backend read: devices/+/uplink/#",
        "backend write: devices/+/downlink/#"
      ]
    },
    null,
    2
  )
);
