import http from 'k6/http';
import { check, sleep } from 'k6';
import { Rate, Trend } from 'k6/metrics';
import { BASE_URL, SLA_THRESHOLDS } from '../lib/config.js';

/**
 * Advanced Search Load Test — Goodgo Platform
 *
 * Tests combined geo + text + filter queries against /search and /search/geo
 * endpoints. Simulates real user behaviour: multi-filter search, pagination,
 * sort variations, and geo-bounded text queries.
 */

const advancedSearchDuration = new Trend('advanced_search_duration', true);
const geoFilterDuration = new Trend('geo_filter_search_duration', true);
const paginatedSearchDuration = new Trend('paginated_search_duration', true);
const searchFailRate = new Rate('advanced_search_failures');

export const options = {
  scenarios: {
    advanced_search_load: {
      executor: 'ramping-vus',
      startVUs: 0,
      stages: [
        { duration: '30s', target: 50 },    // warm up
        { duration: '1m', target: 200 },     // ramp to peak
        { duration: '1m', target: 300 },     // stress peak
        { duration: '30s', target: 0 },      // ramp down
      ],
      gracefulRampDown: '10s',
    },
  },
  thresholds: {
    ...SLA_THRESHOLDS,
    advanced_search_duration: ['p(95)<800'],
    geo_filter_search_duration: ['p(95)<800'],
    paginated_search_duration: ['p(95)<500'],
    advanced_search_failures: ['rate<0.05'],
  },
};

// Vietnamese text queries combined with property filters
const COMBINED_QUERIES = [
  { q: 'căn hộ', propertyType: 'APARTMENT', transactionType: 'SALE', priceMin: 1000000000, priceMax: 5000000000 },
  { q: 'nhà phố', propertyType: 'HOUSE', transactionType: 'SALE', city: 'TP. Hồ Chí Minh' },
  { q: 'đất nền', propertyType: 'LAND', areaMin: 100, areaMax: 500, district: 'Quận 9' },
  { q: 'chung cư', transactionType: 'RENT', priceMin: 5000000, priceMax: 20000000, bedrooms: 2 },
  { q: 'biệt thự', propertyType: 'HOUSE', areaMin: 200, city: 'Hà Nội' },
  { q: 'apartment', transactionType: 'SALE', priceMin: 2000000000, bedrooms: 3 },
  { q: 'phòng trọ', transactionType: 'RENT', priceMax: 5000000 },
  { q: 'villa', propertyType: 'HOUSE', areaMin: 300, priceMin: 10000000000 },
];

// Geo-bounded searches with various radii and filters
const GEO_FILTER_QUERIES = [
  { lat: 10.7769, lng: 106.7009, radiusKm: 5, propertyType: 'APARTMENT', transactionType: 'SALE' },
  { lat: 10.7769, lng: 106.7009, radiusKm: 2, propertyType: 'HOUSE', priceMin: 3000000000 },
  { lat: 21.0285, lng: 105.8542, radiusKm: 3, transactionType: 'RENT', bedrooms: 2 },
  { lat: 10.8231, lng: 106.6297, radiusKm: 1, propertyType: 'LAND', areaMin: 50 },
  { lat: 16.0544, lng: 108.2022, radiusKm: 10, transactionType: 'SALE' },
  { lat: 21.0067, lng: 105.8400, radiusKm: 5, propertyType: 'APARTMENT', priceMax: 5000000000 },
  { lat: 10.8500, lng: 106.7700, radiusKm: 3, propertyType: 'HOUSE', bedrooms: 3 },
  { lat: 10.7300, lng: 106.6500, radiusKm: 2, transactionType: 'RENT', priceMax: 15000000 },
];

// Sort options
const SORT_OPTIONS = ['priceAsc', 'priceDesc', 'newest', 'areaDesc'];

function buildQueryString(params) {
  const parts = [];
  for (const [key, value] of Object.entries(params)) {
    if (value !== undefined && value !== null) {
      parts.push(`${key}=${encodeURIComponent(value)}`);
    }
  }
  return parts.join('&');
}

export default function () {
  const iter = __ITER;
  const scenario = iter % 5;

  if (scenario <= 1) {
    // --- Combined text + filter search (40% of traffic) ---
    const query = COMBINED_QUERIES[iter % COMBINED_QUERIES.length];
    const sortBy = SORT_OPTIONS[iter % SORT_OPTIONS.length];
    const qs = buildQueryString({
      ...query,
      sortBy,
      page: 1,
      perPage: 20,
    });
    const url = `${BASE_URL}/search?${qs}`;

    const res = http.get(url, {
      tags: { name: 'GET /search (advanced)' },
    });

    advancedSearchDuration.add(res.timings.duration);
    const ok = check(res, {
      'advanced search: status 200|503': (r) => r.status === 200 || r.status === 503,
      'advanced search: valid response': (r) => {
        if (r.status === 503) return true; // Typesense unavailable
        try { return JSON.parse(r.body).data !== undefined; } catch { return false; }
      },
    });
    if (!ok) searchFailRate.add(1);

  } else if (scenario <= 3) {
    // --- Geo + filter search (40% of traffic) ---
    const geoQuery = GEO_FILTER_QUERIES[iter % GEO_FILTER_QUERIES.length];
    const { lat, lng, radiusKm, ...filters } = geoQuery;
    const qs = buildQueryString({
      lat,
      lng,
      radiusKm,
      ...filters,
      limit: 20,
    });
    const url = `${BASE_URL}/search/geo?${qs}`;

    const res = http.get(url, {
      tags: { name: 'GET /search/geo (filtered)' },
    });

    geoFilterDuration.add(res.timings.duration);
    const ok = check(res, {
      'geo filter: status 200|503': (r) => r.status === 200 || r.status === 503,
      'geo filter: valid response': (r) => {
        if (r.status === 503) return true;
        try { return JSON.parse(r.body).data !== undefined; } catch { return false; }
      },
    });
    if (!ok) searchFailRate.add(1);

  } else {
    // --- Paginated deep search (20% of traffic) ---
    const query = COMBINED_QUERIES[iter % COMBINED_QUERIES.length];
    const page = 1 + (iter % 5); // pages 1-5
    const qs = buildQueryString({
      q: query.q,
      propertyType: query.propertyType,
      page,
      perPage: 20,
      sortBy: SORT_OPTIONS[iter % SORT_OPTIONS.length],
    });
    const url = `${BASE_URL}/search?${qs}`;

    const res = http.get(url, {
      tags: { name: 'GET /search (paginated)' },
    });

    paginatedSearchDuration.add(res.timings.duration);
    const ok = check(res, {
      'paginated search: status 200|503': (r) => r.status === 200 || r.status === 503,
    });
    if (!ok) searchFailRate.add(1);
  }

  sleep(Math.random() * 1 + 0.3);
}
