import http from 'k6/http';
import { check, fail, sleep } from 'k6';
import exec from 'k6/execution';

const BASE_URL = (__ENV.BASE_URL || 'https://127.0.0.1:2288').replace(/\/$/, '');
const HOST_HEADER = (__ENV.HOST_HEADER || 'stend.4mont.ru').trim();
const SERVICE_A = __ENV.SERVICE_A || 'termidesk';
const SERVICE_B = __ENV.SERVICE_B || 'vmmanager';
const CLOSE_SESSION = (__ENV.CLOSE_SESSION || '1') !== '0';
const REQ_TIMEOUT = __ENV.REQ_TIMEOUT || '20s';

const users = (__ENV.USERS_CSV || '')
  .split(';')
  .map((v) => v.trim())
  .filter(Boolean)
  .map((pair) => {
    const i = pair.indexOf(':');
    return i > 0 ? { username: pair.slice(0, i), password: pair.slice(i + 1) } : null;
  })
  .filter(Boolean);

export const options = {
  scenarios: {
    burst_100_users: {
      executor: 'per-vu-iterations',
      vus: 100,
      iterations: 1,
      maxDuration: '3m',
    },
  },
  insecureSkipTLSVerify: true,
  thresholds: {
    http_req_failed: ['rate<0.2'],
  },
};

function hdr(extra = {}) {
  return HOST_HEADER ? { ...extra, Host: HOST_HEADER } : extra;
}

function getCreds() {
  if (users.length < 100) fail(`Need at least 100 users in USERS_CSV, got ${users.length}`);
  const idx = (exec.vu.idInTest || 1) - 1;
  return users[idx % users.length];
}

function login(username, password) {
  const jar = http.cookieJar();
  jar.clear(BASE_URL);

  const landing = http.get(`${BASE_URL}/`, {
    redirects: 0,
    timeout: REQ_TIMEOUT,
    headers: hdr(),
    tags: { name: 'GET /' },
  });

  const csrfFromCookie = (jar.cookiesForURL(BASE_URL).csrf_token || [])[0] || '';
  const csrf = csrfFromCookie || ((landing.cookies.csrf_token || [])[0] || {}).value || '';
  if (!csrf) fail(`No CSRF for ${username}`);

  const payload = [
    `username=${encodeURIComponent(username)}`,
    `password=${encodeURIComponent(password)}`,
    `csrf_token=${encodeURIComponent(csrf)}`,
  ].join('&');

  const loginRes = http.post(`${BASE_URL}/login`, payload, {
    redirects: 0,
    timeout: REQ_TIMEOUT,
    headers: hdr({ 'Content-Type': 'application/x-www-form-urlencoded' }),
    tags: { name: 'POST /login' },
  });

  const ok = check(loginRes, { 'login status 303': (r) => r.status === 303 });
  if (!ok) fail(`Login failed ${username}, status=${loginRes.status}`);
}

function openService(slug) {
  const res = http.get(`${BASE_URL}/go/${slug}`, {
    redirects: 0,
    timeout: REQ_TIMEOUT,
    headers: hdr(),
    tags: { name: 'GET /go/:slug' },
  });
  const ok = check(res, { [`open ${slug} -> 303`]: (r) => r.status === 303 });
  const location = res.headers.Location || '';
  const m = location.match(/\/s\/([0-9a-fA-F-]{36})\//);
  return { ok, status: res.status, sessionId: m ? m[1] : '', location };
}

function closeSession(sessionId) {
  if (!sessionId || !CLOSE_SESSION) return;
  http.post(`${BASE_URL}/api/sessions/${sessionId}/close`, null, {
    redirects: 0,
    timeout: REQ_TIMEOUT,
    headers: hdr(),
    tags: { name: 'POST /api/sessions/:id/close' },
  });
}

export default function () {
  const { username, password } = getCreds();
  login(username, password);

  const a = openService(SERVICE_A);
  sleep(0.1);
  const b = openService(SERVICE_B);

  closeSession(a.sessionId);
  closeSession(b.sessionId);

  if (!a.ok || !b.ok) {
    fail(`open failed user=${username} a=${a.status} b=${b.status}`);
  }
}
