/**
 * SCENARIO: auth-flow.js
 * Register → Login → Refresh Token → Logout flow
 *
 * Tujuan: Stress test auth endpoints yang dipakai setiap user saat app dibuka.
 * Target: p95 auth latency < 800ms, error rate < 1%
 */
import { sleep, check } from "k6";
import {
  DEFAULT_THRESHOLDS,
  handleSummary,
  pickThresholds,
} from "../modules/metrics-helper.js";
import * as api from "../modules/api-client.js";
import { testData } from "../modules/test-data.js";
import { registerAndLogin, doRefreshToken } from "../modules/auth-helper.js";

const RUN_ID = __ENV.RUN_ID || `${Date.now()}`;

// ── Konfigurasi test — override via --config atau env ───────────────────────
export const options = {
  scenarios: {
    auth_flow: {
      executor: "ramping-vus",
      startVUs: 0,
      stages: [
        { duration: "30s", target: 10 }, // warm-up
        { duration: "60s", target: 30 }, // ramp-up
        { duration: "60s", target: 30 }, // sustain
        { duration: "30s", target: 0 }, // ramp-down
      ],
      gracefulRampDown: "15s",
    },
  },
  thresholds: pickThresholds(
    __ENV.BENCH_PROFILE === "local"
      ? { walkguide_auth_latency_ms: ["p(95)<35000", "p(99)<40000"] }
      : {
          ...DEFAULT_THRESHOLDS,
          walkguide_auth_latency_ms: ["p(95)<800", "p(99)<1500"],
        },
  ),
};

// ── Main VU function ──────────────────────────────────────────────────────────

export default function authFlow() {
  const vuId = __VU;

  // ── Step 1: Register user baru (setiap VU punya unique email) ───────────────
  const role = vuId % 2 === 0 ? "ROLE_GUARDIAN" : "ROLE_USER";
  const suffix = `${RUN_ID}_${vuId}_${__ITER}`;
  const payload =
    role === "ROLE_GUARDIAN"
      ? testData.guardianRegisterPayload(suffix)
      : testData.userRegisterPayload(suffix);

  const regRes = api.register(payload);
  check(regRes, {
    "register: status 200": (r) => r.status === 200,
    "register: has accessToken": (r) => {
      const b = api.parseBody(r);
      return b && b.data && !!b.data.accessToken;
    },
  });

  let tokens = null;
  if (regRes.status === 200) {
    const body = api.parseBody(regRes);
    if (body && body.data) tokens = body.data;
  }

  sleep(0.5);

  // ── Step 2: Login ulang dengan credentials yang sama ────────────────────────
  const loginRes = api.login(payload.email, payload.password);
  check(loginRes, {
    "login: status 200": (r) => r.status === 200,
    "login: accessToken set": (r) => {
      const b = api.parseBody(r);
      return b && b.data && !!b.data.accessToken;
    },
    "login: refreshToken set": (r) => {
      const b = api.parseBody(r);
      return b && b.data && !!b.data.refreshToken;
    },
    "login: role correct": (r) => {
      const b = api.parseBody(r);
      return b && b.data && b.data.role === role;
    },
  });

  if (loginRes.status === 200) {
    const body = api.parseBody(loginRes);
    if (body && body.data) tokens = body.data;
  }

  sleep(0.3);

  // ── Step 3: Refresh token (simulasi token expire) ───────────────────────────
  if (tokens && tokens.refreshToken) {
    const refreshRes = api.refreshToken(tokens.refreshToken);
    check(refreshRes, {
      "refresh: status 200": (r) => r.status === 200,
      "refresh: new accessToken": (r) => {
        const b = api.parseBody(r);
        return b && b.data && !!b.data.accessToken;
      },
    });

    // Update access token
    if (refreshRes.status === 200) {
      const body = api.parseBody(refreshRes);
      if (body && body.data) tokens.accessToken = body.data.accessToken;
    }
  }

  sleep(0.3);

  // ── Step 4: Update FCM token (dilakukan tiap login di production) ───────────
  if (tokens && tokens.accessToken) {
    const fakeFcm = `fcm_${Math.random().toString(36).slice(2, 30)}:APA91b${Math.random().toString(36).slice(2, 50)}`;
    const fcmRes = api.updateFcmToken(tokens.accessToken, fakeFcm);
    check(fcmRes, {
      "fcm-token: status 2xx": (r) => r.status >= 200 && r.status < 300,
    });
  }

  sleep(0.2);

  // ── Step 5: Logout ──────────────────────────────────────────────────────────
  if (tokens && tokens.accessToken) {
    const logoutRes = api.logout(tokens.accessToken);
    check(logoutRes, {
      "logout: status 2xx": (r) => r.status >= 200 && r.status < 300,
    });
  }

  // ── Think time: user nyata butuh beberapa detik antar aksi ──────────────────
  sleep(testData.randomFloat(0.5, 1.5, 1));
}

// ── Health check sebelum test dimulai ────────────────────────────────────────
export function setup() {
  const res = api.ping();
  if (res.status !== 200) {
    throw new Error(
      `Backend tidak reachable. Ping returned ${res.status}. URL: ${__ENV.BASE_URL || "http://202.46.28.160:8080"}`,
    );
  }
  console.log("✅ Backend reachable. Auth flow test starting.");
}

export { handleSummary };
