/**
 * WalkGuide — JWT Token Management Helper
 * Mengelola login, penyimpanan token, dan auto-refresh untuk k6 VUs.
 */
import { check, sleep } from "k6";
import * as api from "./api-client.js";
import { testData } from "./test-data.js";

// ── Shared token cache (per VU, tidak cross-VU karena k6 isolasi per VU) ────
let _cachedTokens = null; // { accessToken, refreshToken, role, userId, uniqueUserId }

/**
 * Login dan simpan token di memory VU ini.
 * Return { accessToken, refreshToken, role, userId }
 */
export function loginAndStore(email, password) {
  const res = api.login(email, password);
  check(res, { "auth-helper: login 200": (r) => r.status === 200 });

  if (res.status !== 200) {
    console.error(
      `[auth-helper] Login failed for ${email}: ${res.status} ${res.body}`,
    );
    return null;
  }

  const body = api.parseBody(res);
  if (!body || !body.data || !body.data.accessToken) {
    console.error(`[auth-helper] Unexpected login response: ${res.body}`);
    return null;
  }

  _cachedTokens = {
    accessToken: body.data.accessToken,
    refreshToken: body.data.refreshToken,
    role: body.data.role,
    userId: body.data.userId,
    uniqueUserId: body.data.uniqueUserId || null,
  };
  return _cachedTokens;
}

/**
 * Register user baru, lalu login. Return token set.
 */
export function registerAndLogin(payload) {
  const regRes = api.register(payload);
  check(regRes, {
    "auth-helper: register 2xx": (r) => r.status >= 200 && r.status < 300,
  });

  if (regRes.status !== 200 && regRes.status !== 201) {
    // Mungkin email sudah ada — coba login saja
    console.warn(
      `[auth-helper] Register failed (${regRes.status}), attempting login.`,
    );
  }

  const body = api.parseBody(regRes);
  // Kalau register langsung return token (sesuai AuthService):
  if (body && body.data && body.data.accessToken) {
    _cachedTokens = {
      accessToken: body.data.accessToken,
      refreshToken: body.data.refreshToken,
      role: body.data.role,
      userId: body.data.userId,
      uniqueUserId: body.data.uniqueUserId || null,
    };
    return _cachedTokens;
  }

  // Fallback: login manual
  return loginAndStore(payload.email, payload.password);
}

/**
 * Ambil access token dari cache. Kalau null, throw agar test gagal eksplisit.
 */
export function getAccessToken() {
  if (!_cachedTokens || !_cachedTokens.accessToken) {
    throw new Error(
      "[auth-helper] No access token in cache. Call loginAndStore() first.",
    );
  }
  return _cachedTokens.accessToken;
}

export function getRefreshToken() {
  if (!_cachedTokens || !_cachedTokens.refreshToken) {
    throw new Error("[auth-helper] No refresh token in cache.");
  }
  return _cachedTokens.refreshToken;
}

export function getCachedTokens() {
  return _cachedTokens;
}

export function getCachedUniqueUserId() {
  return _cachedTokens ? _cachedTokens.uniqueUserId : null;
}

/**
 * Refresh access token menggunakan refresh token yang tersimpan.
 * Update cache dengan access token baru.
 */
export function doRefreshToken() {
  const rt = getRefreshToken();
  const res = api.refreshToken(rt);
  check(res, { "auth-helper: refresh 200": (r) => r.status === 200 });

  if (res.status !== 200) {
    console.error(`[auth-helper] Refresh token failed: ${res.status}`);
    return null;
  }

  const body = api.parseBody(res);
  if (body && body.data && body.data.accessToken) {
    _cachedTokens.accessToken = body.data.accessToken;
  }
  return _cachedTokens.accessToken;
}

/**
 * Clear semua cached token (simulasi logout).
 */
export function clearTokens() {
  _cachedTokens = null;
}

// ── Pre-built credential sets untuk smoke/load test ──────────────────────────
// Test users yang sudah ada di DB kampus (V2__seed_users.sql)
// Jika tidak ada, gunakan dynamic register.

export const PREBUILT_GUARDIAN = {
  email: __ENV.GUARDIAN_EMAIL || "guardian@walkguide.test",
  password: __ENV.GUARDIAN_PASSWORD || "Guardian123!",
};

export const PREBUILT_USER = {
  email: __ENV.USER_EMAIL || "user@walkguide.test",
  password: __ENV.USER_PASSWORD || "User123!",
};

/**
 * Setup pair: register guardian + user, lalu pairing.
 * Return { guardianTokens, userTokens }
 */
export function setupPairedSession() {
  const suffix = `${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;

  // Register guardian
  const gPayload = testData.guardianRegisterPayload(suffix);
  const gTokens = registerAndLogin(gPayload);
  if (!gTokens) return null;

  // Register user
  const uPayload = testData.userRegisterPayload(suffix);
  const uTokens = registerAndLogin(uPayload);
  if (!uTokens) return null;

  return {
    guardianTokens: gTokens,
    userTokens: uTokens,
    guardianPayload: gPayload,
    userPayload: uPayload,
  };
}
