import http from 'k6/http';
import { check, group, sleep } from 'k6';
import { Rate, Trend, Counter } from 'k6/metrics';
import { randomIntBetween } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';

// Custom metrics
const errorRate = new Rate('errors');
const responseTime = new Trend('response_time');
const throughput = new Counter('throughput');
const loginFailures = new Counter('login_failures');

// Test configuration
export const options = {
  scenarios: {
    // Smoke test - low load to verify system works
    smoke: {
      executor: 'constant-vus',
      vus: 10,
      duration: '1m',
      tags: { test_type: 'smoke' },
    },
    // Load test - 100 concurrent users
    load_100: {
      executor: 'ramping-vus',
      startVUs: 0,
      stages: [
        { duration: '2m', target: 100 },
        { duration: '5m', target: 100 },
        { duration: '2m', target: 0 },
      ],
      tags: { test_type: 'load_100' },
    },
    // Load test - 500 concurrent users
    load_500: {
      executor: 'ramping-vus',
      startVUs: 0,
      stages: [
        { duration: '3m', target: 500 },
        { duration: '10m', target: 500 },
        { duration: '3m', target: 0 },
      ],
      tags: { test_type: 'load_500' },
    },
    // Load test - 1000 concurrent users
    load_1000: {
      executor: 'ramping-vus',
      startVUs: 0,
      stages: [
        { duration: '5m', target: 1000 },
        { duration: '15m', target: 1000 },
        { duration: '5m', target: 0 },
      ],
      tags: { test_type: 'load_1000' },
    },
  },
  thresholds: {
    // Performance requirements
    http_req_duration: ['p(95)<200'], // 95th percentile < 200ms
    http_req_duration: ['p(50)<100'], // 50th percentile < 100ms
    http_req_failed: ['rate<0.01'],   // Error rate < 1%
    errors: ['rate<0.01'],
    // Throughput requirements
    throughput: ['count>1000'],
  },
};

const BASE_URL = __ENV.BASE_URL || 'http://localhost:8000';
const API_V1 = `${BASE_URL}/api/v1`;

// Test data
testData = {
  username: `loadtest_${randomIntBetween(1, 10000)}@test.com`,
  password: 'TestPassword123!',
  scenarioName: `LoadTest_Scenario_${randomIntBetween(1, 1000)}`,
};

export function setup() {
  console.log('Starting load test setup...');
  
  // Health check
  const healthCheck = http.get(`${BASE_URL}/health`);
  check(healthCheck, {
    'health check status is 200': (r) => r.status === 200,
  });
  
  // Register test user
  const registerRes = http.post(`${API_V1}/auth/register`, JSON.stringify({
    email: testData.username,
    password: testData.password,
    full_name: 'Load Test User',
  }), {
    headers: { 'Content-Type': 'application/json' },
  });
  
  let authToken = null;
  
  if (registerRes.status === 201) {
    // Login to get token
    const loginRes = http.post(`${API_V1}/auth/login`, JSON.stringify({
      username: testData.username,
      password: testData.password,
    }), {
      headers: { 'Content-Type': 'application/json' },
    });
    
    if (loginRes.status === 200) {
      authToken = JSON.parse(loginRes.body).access_token;
    }
  }
  
  return { authToken, testData };
}

export default function(data) {
  const params = {
    headers: {
      'Content-Type': 'application/json',
      ...(data.authToken && { 'Authorization': `Bearer ${data.authToken}` }),
    },
  };
  
  group('API Health & Info', () => {
    // Health endpoint
    const healthRes = http.get(`${BASE_URL}/health`, params);
    const healthCheck = check(healthRes, {
      'health status is 200': (r) => r.status === 200,
      'health response time < 100ms': (r) => r.timings.duration < 100,
    });
    errorRate.add(!healthCheck);
    responseTime.add(healthRes.timings.duration);
    throughput.add(1);
    
    // API docs
    const docsRes = http.get(`${BASE_URL}/docs`, params);
    check(docsRes, {
      'docs status is 200': (r) => r.status === 200,
    });
  });
  
  group('Authentication', () => {
    // Login endpoint - high frequency
    const loginRes = http.post(`${API_V1}/auth/login`, JSON.stringify({
      username: data.testData.username,
      password: data.testData.password,
    }), params);
    
    const loginCheck = check(loginRes, {
      'login status is 200': (r) => r.status === 200,
      'login response time < 500ms': (r) => r.timings.duration < 500,
      'login returns access_token': (r) => r.json('access_token') !== undefined,
    });
    
    if (!loginCheck) {
      loginFailures.add(1);
    }
    errorRate.add(!loginCheck);
    responseTime.add(loginRes.timings.duration);
    throughput.add(1);
  });
  
  group('Scenarios API', () => {
    // List scenarios
    const listRes = http.get(`${API_V1}/scenarios?page=1&page_size=20`, params);
    const listCheck = check(listRes, {
      'list scenarios status is 200': (r) => r.status === 200,
      'list scenarios response time < 200ms': (r) => r.timings.duration < 200,
    });
    errorRate.add(!listCheck);
    responseTime.add(listRes.timings.duration);
    throughput.add(1);
    
    // Create scenario (20% of requests)
    if (Math.random() < 0.2) {
      const createRes = http.post(`${API_V1}/scenarios`, JSON.stringify({
        name: `${data.testData.scenarioName}_${randomIntBetween(1, 10000)}`,
        description: 'Load test scenario',
        region: 'us-east-1',
        tags: ['load-test', 'performance'],
      }), params);
      
      const createCheck = check(createRes, {
        'create scenario status is 201': (r) => r.status === 201,
        'create scenario response time < 500ms': (r) => r.timings.duration < 500,
      });
      errorRate.add(!createCheck);
      responseTime.add(createRes.timings.duration);
      throughput.add(1);
    }
  });
  
  group('Metrics API', () => {
    // Get dashboard metrics
    const metricsRes = http.get(`${API_V1}/metrics/dashboard`, params);
    const metricsCheck = check(metricsRes, {
      'metrics status is 200': (r) => r.status === 200,
      'metrics response time < 300ms': (r) => r.timings.duration < 300,
    });
    errorRate.add(!metricsCheck);
    responseTime.add(metricsRes.timings.duration);
    throughput.add(1);
  });
  
  group('Ingest API', () => {
    // Simulate log ingestion
    const ingestRes = http.post(`${BASE_URL}/ingest`, JSON.stringify({
      message: `Load test log entry ${randomIntBetween(1, 1000000)}`,
      source: 'load-test',
      level: 'INFO',
      metadata: {
        service: 'load-test-service',
        request_id: `req_${randomIntBetween(1, 1000000)}`,
      },
    }), {
      ...params,
      headers: {
        ...params.headers,
        'X-Scenario-ID': `scenario_${randomIntBetween(1, 100)}`,
      },
    });
    
    const ingestCheck = check(ingestRes, {
      'ingest status is 200 or 202': (r) => r.status === 200 || r.status === 202,
      'ingest response time < 100ms': (r) => r.timings.duration < 100,
    });
    errorRate.add(!ingestCheck);
    responseTime.add(ingestRes.timings.duration);
    throughput.add(1);
  });
  
  group('Reports API', () => {
    // List reports
    const reportsRes = http.get(`${API_V1}/reports?page=1&page_size=10`, params);
    const reportsCheck = check(reportsRes, {
      'reports list status is 200': (r) => r.status === 200,
      'reports list response time < 300ms': (r) => r.timings.duration < 300,
    });
    errorRate.add(!reportsCheck);
    responseTime.add(reportsRes.timings.duration);
    throughput.add(1);
  });
  
  // Random sleep between 1-3 seconds to simulate real user behavior
  sleep(randomIntBetween(1, 3));
}

export function teardown(data) {
  console.log('Load test completed. Cleaning up...');
  
  // Cleanup test data if needed
  if (data.authToken) {
    const params = {
      headers: {
        'Authorization': `Bearer ${data.authToken}`,
        'Content-Type': 'application/json',
      },
    };
    
    // Delete test scenarios created during load test
    http.del(`${API_V1}/scenarios/cleanup-load-test`, null, params);
  }
  
  console.log('Cleanup completed.');
}
