import assert from "node:assert/strict";
import { test } from "bun:test";

import { createUserBillingClient } from "./user-billing-client.ts";

test("user-billing login retries transient dependency failures only", async () => {
  const calls = [];
  const client = createUserBillingClient({
    env: {
      HWLAB_USER_BILLING_URL: "http://user-billing.test",
      HWLAB_USER_BILLING_LOGIN_RETRY_ATTEMPTS: "2",
      HWLAB_USER_BILLING_LOGIN_RETRY_DELAY_MS: "1"
    },
    fetchImpl: async (url, init) => {
      calls.push({ url: String(url), method: init?.method });
      if (calls.length === 1) throw new Error("The operation timed out.");
      return new Response(JSON.stringify({ token: "hws_retry_ok", tokenType: "Bearer" }), { status: 200, headers: { "content-type": "application/json" } });
    }
  });

  const result = await client.login({ username: "admin", password: "redacted" });
  assert.equal(result.ok, true);
  assert.equal(result.retryCount, 1);
  assert.equal(result.transientObserved, true);
  assert.equal(calls.length, 2);

  const authFailures = [];
  const invalidClient = createUserBillingClient({
    env: {
      HWLAB_USER_BILLING_URL: "http://user-billing.test",
      HWLAB_USER_BILLING_LOGIN_RETRY_ATTEMPTS: "2",
      HWLAB_USER_BILLING_LOGIN_RETRY_DELAY_MS: "1"
    },
    fetchImpl: async (url, init) => {
      authFailures.push({ url: String(url), method: init?.method });
      return new Response(JSON.stringify({ error: { code: "invalid_credentials", message: "invalid email, username or password" } }), { status: 401, headers: { "content-type": "application/json" } });
    }
  });

  const invalid = await invalidClient.login({ username: "admin", password: "wrong" });
  assert.equal(invalid.ok, false);
  assert.equal(invalid.status, 401);
  assert.equal(invalid.error.code, "invalid_credentials");
  assert.equal(authFailures.length, 1);

  const unexpectedCalls = [];
  const unconfiguredClient = createUserBillingClient({
    env: {
      HWLAB_USER_BILLING_LOGIN_RETRY_ATTEMPTS: "2",
      HWLAB_USER_BILLING_LOGIN_RETRY_DELAY_MS: "1"
    },
    fetchImpl: async (url, init) => {
      unexpectedCalls.push({ url: String(url), method: init?.method });
      throw new Error("fetch should not run without a user-billing URL");
    }
  });

  const unconfigured = await unconfiguredClient.login({ username: "admin", password: "redacted" });
  assert.equal(unconfigured.ok, false);
  assert.equal(unconfigured.status, 503);
  assert.equal(unconfigured.error.code, "user_billing_not_configured");
  assert.equal(unconfigured.retryable, undefined);
  assert.equal(unexpectedCalls.length, 0);
});

test("user-billing login propagates traceparent to dependency requests", async () => {
  const traceparent = "00-11111111111111111111111111111111-2222222222222222-01";
  const calls = [];
  const client = createUserBillingClient({
    env: { HWLAB_USER_BILLING_URL: "http://user-billing.test" },
    fetchImpl: async (url, init) => {
      calls.push({ url: String(url), traceparent: init?.headers?.traceparent });
      return new Response(JSON.stringify({ token: "hws_trace_ok", tokenType: "Bearer" }), { status: 200, headers: { "content-type": "application/json" } });
    }
  });

  const result = await client.login({ username: "admin", password: "redacted" }, { traceparent });
  assert.equal(result.ok, true);
  assert.equal(calls.length, 1);
  assert.equal(calls[0].traceparent, traceparent);
});
