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

const baseUrl = (__ENV.TIKU_BASE_URL || 'http://localhost:5091').replace(/\/$/, '');
const tenantCode = __ENV.TIKU_TENANT_CODE || 'demo-crm-school';
const hostHeader = __ENV.TIKU_HOST_HEADER || '';
const mode = (__ENV.TIKU_MODE || 'mixed').toLowerCase();
const rate = positiveInteger('TIKU_RATE', 100);
const duration = __ENV.TIKU_DURATION || '30s';
const preAllocatedVUs = positiveInteger('TIKU_PRE_ALLOCATED_VUS', Math.max(20, Math.ceil(rate / 20)));
const maxVUs = positiveInteger('TIKU_MAX_VUS', Math.max(100, preAllocatedVUs * 4));

if (!['mixed', 'hot', 'cold', 'ready'].includes(mode)) {
  throw new Error(`Unsupported TIKU_MODE '${mode}'. Use mixed, hot, cold, or ready.`);
}

export const options = {
  discardResponseBodies: true,
  summaryTrendStats: ['avg', 'min', 'med', 'p(90)', 'p(95)', 'p(99)', 'max'],
  scenarios: {
    api: {
      executor: 'constant-arrival-rate',
      exec: 'apiTraffic',
      rate,
      timeUnit: '1s',
      duration,
      preAllocatedVUs,
      maxVUs,
      gracefulStop: '5s',
    },
  },
  thresholds: {
    checks: ['rate>0.99'],
    http_req_failed: ['rate<0.01'],
    http_req_duration: ['p(95)<500', 'p(99)<1000'],
    dropped_iterations: ['count==0'],
  },
};

const tenantHeaders = {
  'x-tenant-code': tenantCode,
  Accept: 'application/json',
  ...(hostHeader ? { Host: hostHeader } : {}),
};

const platformHeaders = hostHeader ? { Host: hostHeader } : {};

export function setup() {
  const ready = http.get(`${baseUrl}/api/health/ready`, {
    headers: platformHeaders,
    responseType: 'text',
    tags: { endpoint: 'ready', phase: 'setup' },
  });
  if (ready.status !== 200) {
    fail(`API dependencies are not ready: status=${ready.status} body=${ready.body}`);
  }

  let readiness;
  try {
    readiness = ready.json();
  } catch (error) {
    fail(`Readiness endpoint did not return JSON: ${error}`);
  }
  if (readiness.status !== 'ready') {
    fail(`PostgreSQL and Redis must both be ready: ${JSON.stringify(readiness)}`);
  }

  const catalog = http.get(`${baseUrl}/api/catalog/regions`, {
    headers: tenantHeaders,
    tags: { endpoint: 'catalog_hot', phase: 'setup' },
  });
  if (catalog.status !== 200) {
    fail(`Tenant '${tenantCode}' is not usable: status=${catalog.status} body=${catalog.body}`);
  }
}

export function apiTraffic() {
  const selected = selectEndpoint();
  let response;

  if (selected === 'ready') {
    response = http.get(`${baseUrl}/api/health/ready`, {
      headers: platformHeaders,
      tags: { endpoint: 'ready' },
    });
  } else if (selected === 'cold') {
    // A unique query string bypasses output-cache reuse while exercising the same
    // tenant resolution and PostgreSQL-backed catalog query as the hot request.
    const cacheBuster = `${__VU}-${__ITER}`;
    response = http.get(`${baseUrl}/api/catalog/regions?loadProbe=${cacheBuster}`, {
      headers: tenantHeaders,
      tags: { endpoint: 'catalog_cold' },
    });
  } else {
    response = http.get(`${baseUrl}/api/catalog/regions`, {
      headers: tenantHeaders,
      tags: { endpoint: 'catalog_hot' },
    });
  }

  check(response, {
    [`${selected} returned 200`]: (result) => result.status === 200,
  });
}

function selectEndpoint() {
  if (mode !== 'mixed') return mode;

  // Stable 70/20/10 traffic mix: cached catalog / uncached catalog / dependency readiness.
  const bucket = (__ITER + __VU) % 10;
  if (bucket === 0) return 'ready';
  if (bucket <= 2) return 'cold';
  return 'hot';
}

function positiveInteger(name, fallback) {
  const raw = __ENV[name];
  if (raw === undefined || raw === '') return fallback;

  const value = Number(raw);
  if (!Number.isInteger(value) || value <= 0) {
    throw new Error(`${name} must be a positive integer, got '${raw}'.`);
  }
  return value;
}
