import http from 'k6/http';
import { check } from 'k6';

// Base URL — override via environment variable: k6 run -e BASE_URL=http://...
const BASE_URL = __ENV.BASE_URL || 'http://localhost:3000';

/**
 * Generate a unique username for a virtual user.
 * Combines VU id, iteration count, and a random suffix to avoid collisions.
 */
export function randomUsername() {
  const rand = Math.random().toString(36).substring(2, 8);
  return `loaduser_${__VU}_${__ITER}_${rand}`;
}

/**
 * Generate a unique email for a virtual user.
 */
export function randomEmail() {
  const rand = Math.random().toString(36).substring(2, 8);
  return `loaduser_${__VU}_${__ITER}_${rand}@loadtest.local`;
}

/**
 * Register a new user account.
 *
 * @param {string} [username] - Username (auto-generated if omitted)
 * @param {string} [email]    - Email (auto-generated if omitted)
 * @param {string} [password] - Password (defaults to 'LoadTest1234!')
 * @returns {{ username: string, email: string, password: string, response: object }}
 */
export function registerUser(username, email, password) {
  username = username || randomUsername();
  email = email || randomEmail();
  password = password || 'LoadTest1234!';

  const payload = JSON.stringify({ username, email, password });
  const params = {
    headers: { 'Content-Type': 'application/json' },
    tags: { name: 'register' },
  };

  const res = http.post(`${BASE_URL}/api/auth/register`, payload, params);

  check(res, {
    'register: status is 201 or 200': (r) => r.status === 201 || r.status === 200,
    'register: body has access token or id': (r) => {
      try {
        const body = r.json();
        return body.access_token !== undefined || body.token !== undefined || body.id !== undefined;
      } catch (_) {
        return false;
      }
    },
  });

  return { username, email, password, response: res };
}

/**
 * Log in with credentials and return the access token.
 *
 * @param {string} email
 * @param {string} password
 * @returns {string|null} access token, or null on failure
 */
export function loginUser(email, password) {
  const payload = JSON.stringify({ email, password });
  const params = {
    headers: { 'Content-Type': 'application/json' },
    tags: { name: 'login' },
  };

  const res = http.post(`${BASE_URL}/api/auth/login`, payload, params);

  const loginOk = check(res, {
    'login: status is 200': (r) => r.status === 200,
    'login: body has access token': (r) => {
      try {
        return r.json('access_token') !== undefined || r.json('token') !== undefined;
      } catch (_) {
        return false;
      }
    },
  });

  if (!loginOk) {
    console.warn(`Login failed for ${email}: ${res.status} ${res.body}`);
    return null;
  }

  return res.json('access_token') || res.json('token');
}

/**
 * Register a new user and immediately log in.
 *
 * @returns {{ token: string|null, username: string, email: string, password: string }}
 */
export function registerAndLogin() {
  const { username, email, password, response: regRes } = registerUser();

  // If the register response already includes an access token, use it directly
  try {
    const regToken = regRes.json('access_token') || regRes.json('token');
    if (regToken) {
      return { token: regToken, username, email, password };
    }
  } catch (_) {
    // fall through to explicit login
  }

  const token = loginUser(email, password);
  return { token, username, email, password };
}

/**
 * Build an authorization header object for authenticated requests.
 *
 * @param {string} token - access token
 * @param {object} [extra] - Additional headers to merge
 * @returns {{ headers: object }}
 */
export function authHeaders(token, extra) {
  const headers = Object.assign(
    { Authorization: `Bearer ${token}` },
    extra || {}
  );
  return { headers };
}

/**
 * Perform an authenticated GET request.
 *
 * @param {string} path  - API path (e.g. '/api/profile')
 * @param {string} token - access token
 * @param {object} [tags] - k6 tags for grouping
 * @returns {object} k6 response
 */
export function authGet(path, token, tags) {
  const params = authHeaders(token);
  if (tags) {
    params.tags = tags;
  }
  return http.get(`${BASE_URL}${path}`, params);
}

/**
 * Perform an authenticated POST request.
 *
 * @param {string} path    - API path
 * @param {object|string} body - Request body (will be JSON-stringified if object)
 * @param {string} token   - access token
 * @param {object} [tags]  - k6 tags for grouping
 * @returns {object} k6 response
 */
export function authPost(path, body, token, tags) {
  const payload = typeof body === 'string' ? body : JSON.stringify(body);
  const params = authHeaders(token, { 'Content-Type': 'application/json' });
  if (tags) {
    params.tags = tags;
  }
  return http.post(`${BASE_URL}${path}`, payload, params);
}

/**
 * Return the configured base URL.
 */
export function getBaseUrl() {
  return BASE_URL;
}
