// Legt in einer frischen Home-Assistant-Instanz einen Testnutzer an und gibt ein
// langlebiges Zugriffstoken auf der Standardausgabe aus. Meldungen gehen auf die
// Fehlerausgabe, damit das aufrufende Skript nur das Token einliest.
// Aufruf: node einrichten.mjs http://localhost:18123

const BASIS = process.argv[2] ?? "http://localhost:18123"
const CLIENT_ID = BASIS + "/"
const BENUTZER = "test"
const PASSWORT = "testtest123"

const melden = (text) => process.stderr.write(`    ${text}\n`)

async function jsonPost(pfad, koerper, token) {
  const kopf = { "Content-Type": "application/json" }
  if (token) kopf.Authorization = `Bearer ${token}`
  const antwort = await fetch(BASIS + pfad, {
    method: "POST",
    headers: kopf,
    body: JSON.stringify(koerper),
  })
  const text = await antwort.text()
  if (!antwort.ok) throw new Error(`${pfad} -> ${antwort.status}: ${text.slice(0, 200)}`)
  return text ? JSON.parse(text) : {}
}

// 1. Onboarding-Schritt "user"
const { auth_code: authCode } = await jsonPost("/api/onboarding/users", {
  client_id: CLIENT_ID,
  name: "Test Nutzer",
  username: BENUTZER,
  password: PASSWORT,
  language: "de",
})
melden("Nutzer angelegt")

// 2. Auth-Code gegen ein kurzlebiges Zugriffstoken tauschen
const tokenAntwort = await fetch(BASIS + "/auth/token", {
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body: new URLSearchParams({
    grant_type: "authorization_code",
    code: authCode,
    client_id: CLIENT_ID,
  }).toString(),
})
const token = await tokenAntwort.json()
if (!token.access_token) throw new Error("kein access_token: " + JSON.stringify(token))
melden("Zugriffstoken erhalten")

// 3. Restliche Onboarding-Schritte abschliessen (Fehler sind unkritisch)
for (const [pfad, koerper] of [
  ["/api/onboarding/core_config", {}],
  ["/api/onboarding/analytics", {}],
  ["/api/onboarding/integration", { client_id: CLIENT_ID, redirect_uri: CLIENT_ID }],
]) {
  try {
    await jsonPost(pfad, koerper, token.access_token)
  } catch {
    // Schritt bereits erledigt oder in dieser Version nicht vorhanden
  }
}

// 4. Langlebiges Token ueber die WebSocket-API erzeugen
const wsUrl = BASIS.replace(/^http/, "ws") + "/api/websocket"
const llat = await new Promise((aufloesen, ablehnen) => {
  const ws = new WebSocket(wsUrl)
  const zeitgeber = setTimeout(() => {
    ablehnen(new Error("Zeitueberschreitung beim Erzeugen des Tokens"))
    ws.close()
  }, 20000)
  ws.onmessage = (nachricht) => {
    const daten = JSON.parse(nachricht.data)
    if (daten.type === "auth_required") {
      ws.send(JSON.stringify({ type: "auth", access_token: token.access_token }))
    } else if (daten.type === "auth_ok") {
      ws.send(
        JSON.stringify({
          id: 1,
          type: "auth/long_lived_access_token",
          client_name: `DataMetric360 Test ${Date.now()}`,
          lifespan: 365,
        }),
      )
    } else if (daten.type === "result") {
      clearTimeout(zeitgeber)
      if (daten.success) aufloesen(daten.result)
      else ablehnen(new Error(JSON.stringify(daten.error)))
      ws.close()
    } else if (daten.type === "auth_invalid") {
      clearTimeout(zeitgeber)
      ablehnen(new Error("auth_invalid"))
      ws.close()
    }
  }
  ws.onerror = () => {
    clearTimeout(zeitgeber)
    ablehnen(new Error("WebSocket-Verbindung fehlgeschlagen"))
  }
})
melden("langlebiges Token erzeugt")

process.stdout.write(llat)
