// k6 load test pour veza-backend-api
// Installation: https://k6.io/docs/getting-started/installation/
// Usage: k6 run scripts/loadtest/k6_load_test.js

import http from 'k6/http';
import { check, sleep } from 'k6';
import { Rate, Trend } from 'k6/metrics';

// Métriques custom
const errorRate = new Rate('errors');
const healthCheckDuration = new Trend('health_check_duration');
const readyzCheckDuration = new Trend('readyz_check_duration');

// Configuration
export const options = {
  stages: [
    { duration: '30s', target: 10 },  // Ramp-up: 0 à 10 VUs en 30s
    { duration: '1m', target: 10 },    // Stabilité: 10 VUs pendant 1m
    { duration: '30s', target: 0 },   // Ramp-down: 10 à 0 VUs en 30s
  ],
  thresholds: {
    'http_req_duration': ['p(95)<500', 'p(99)<1000'], // 95% < 500ms, 99% < 1s
    'errors': ['rate<0.05'],                          // < 5% d'erreurs
    'health_check_duration': ['p(95)<100'],           // Health check < 100ms
    'readyz_check_duration': ['p(95)<200'],           // Readyz check < 200ms
  },
};

// Base URL (configurable via env)
const BASE_URL = __ENV.BASE_URL || 'http://localhost:8080';

// Token pour endpoints authentifiés (optionnel, pour tests auth)
const AUTH_TOKEN = __ENV.AUTH_TOKEN || '';

export default function () {
  // 1. Health check (/health)
  const healthRes = http.get(`${BASE_URL}/health`);
  const healthCheck = check(healthRes, {
    'health status is 200': (r) => r.status === 200,
    'health response has status': (r) => {
      try {
        const body = JSON.parse(r.body);
        return body.success === true && body.data && body.data.status;
      } catch (e) {
        return false;
      }
    },
  });
  errorRate.add(!healthCheck);
  healthCheckDuration.add(healthRes.timings.duration);

  sleep(0.5);

  // 2. Readiness check (/readyz)
  const readyzRes = http.get(`${BASE_URL}/readyz`);
  const readyzCheck = check(readyzRes, {
    'readyz status is 200': (r) => r.status === 200,
    'readyz response has status': (r) => {
      try {
        const body = JSON.parse(r.body);
        return body.success === true && body.data && body.data.status;
      } catch (e) {
        return false;
      }
    },
  });
  errorRate.add(!readyzCheck);
  readyzCheckDuration.add(readyzRes.timings.duration);

  sleep(0.5);

  // 3. Auth endpoint (POST /api/v1/auth/login) - test avec credentials invalides (attendu: 401)
  const loginPayload = JSON.stringify({
    email: 'test@example.com',
    password: 'invalid_password',
  });
  const loginRes = http.post(`${BASE_URL}/api/v1/auth/login`, loginPayload, {
    headers: { 'Content-Type': 'application/json' },
  });
  const loginCheck = check(loginRes, {
    'login returns 401 or 400': (r) => r.status === 401 || r.status === 400,
    'login error format is correct': (r) => {
      try {
        const body = JSON.parse(r.body);
        return body.success === false && body.error;
      } catch (e) {
        return false;
      }
    },
  });
  errorRate.add(!loginCheck);

  sleep(1);

  // 4. Track list endpoint (GET /api/v1/tracks) - sans auth (attendu: 401 ou 200 selon config)
  const tracksRes = http.get(`${BASE_URL}/api/v1/tracks`, {
    headers: AUTH_TOKEN ? { 'Authorization': `Bearer ${AUTH_TOKEN}` } : {},
  });
  const tracksCheck = check(tracksRes, {
    'tracks returns 200 or 401': (r) => r.status === 200 || r.status === 401,
  });
  errorRate.add(tracksRes.status >= 500); // Seulement erreurs 5xx comptent comme erreurs

  sleep(1);
}

export function handleSummary(data) {
  return {
    'stdout': textSummary(data, { indent: ' ', enableColors: true }),
    'scripts/loadtest/k6_summary.json': JSON.stringify(data),
  };
}

function textSummary(data, options) {
  const indent = options.indent || '';
  const enableColors = options.enableColors || false;
  
  let summary = '\n';
  summary += `${indent}Load Test Summary\n`;
  summary += `${indent}==================\n\n`;
  
  // HTTP Requests
  summary += `${indent}HTTP Requests:\n`;
  summary += `${indent}  Total: ${data.metrics.http_reqs.values.count}\n`;
  summary += `${indent}  Failed: ${data.metrics.http_req_failed.values.rate * 100}%\n\n`;
  
  // Durations
  summary += `${indent}Durations:\n`;
  summary += `${indent}  P95: ${data.metrics.http_req_duration.values['p(95)']}ms\n`;
  summary += `${indent}  P99: ${data.metrics.http_req_duration.values['p(99)']}ms\n\n`;
  
  // Health checks
  if (data.metrics.health_check_duration) {
    summary += `${indent}Health Check:\n`;
    summary += `${indent}  P95: ${data.metrics.health_check_duration.values['p(95)']}ms\n`;
  }
  
  if (data.metrics.readyz_check_duration) {
    summary += `${indent}Readyz Check:\n`;
    summary += `${indent}  P95: ${data.metrics.readyz_check_duration.values['p(95)']}ms\n`;
  }
  
  return summary;
}
