/**
 * Admin Operations Load Test
 *
 * Simulates 20 concurrent admin users performing management operations
 * Tests:
 * - Login
 * - List collections (Pages, Posts, Portfolio)
 * - View/edit items
 * - Create new items
 * - Delete items
 *
 * NFR4 Requirements:
 * - p95 response time < 700ms (slightly more lenient for admin)
 * - Error rate < 1%
 * - 20 concurrent users sustained for 3 minutes
 */

import { check, group } from 'k6';
import { urls, thresholdGroups, config } from './lib/config.js';
import { AuthHelper, ApiHelper, thinkTime, testData } from './lib/helpers.js';

// Test configuration
export const options = {
  stages: config.stages.adminOperations,
  thresholds: thresholdGroups.admin,
  ...config.requestOptions,
};

// Store auth token per VU
let authToken = null;
let apiHelper = null;

/**
 * Setup and login - runs once per VU
 */
export function setup() {
  console.log('=== Admin Operations Load Test ===');
  console.log(`Target: ${config.baseUrl}`);
  console.log(`Admin: ${config.adminEmail}`);
  console.log('Starting test...');
}

/**
 * Login function
 */
function login() {
  const auth = new AuthHelper(config.baseUrl);
  const { success } = auth.login(config.adminEmail, config.adminPassword);

  if (!success) {
    console.error('Login failed!');
    return null;
  }

  apiHelper = new ApiHelper(config.baseUrl);
  apiHelper.setToken(auth.token);
  return auth.token;
}

/**
 * Main test scenario
 */
export default function () {
  // Login if not authenticated
  if (!authToken) {
    group('Admin Login', () => {
      authToken = login();
      thinkTime(1, 2);
    });

    if (!authToken) {
      // Cannot proceed without auth
      return;
    }
  }

  // Scenario 1: Browse collections (read operations)
  group('List Collections', () => {
    // List pages
    apiHelper.get('/pages', { limit: 10, depth: 1 });
    thinkTime(0.5, 1);

    // List posts
    apiHelper.get('/posts', { limit: 10, depth: 1 });
    thinkTime(0.5, 1);

    // List portfolio
    apiHelper.get('/portfolio', { limit: 10, depth: 1 });
    thinkTime(0.5, 1);
  });

  // Scenario 2: View specific items (read operations)
  group('View Items', () => {
    // Try to view first item from each collection
    try {
      const pages = apiHelper.get('/pages', { limit: 1, depth: 0 });
      if (pages.status === 200 && pages.json('totalDocs') > 0) {
        const firstId = pages.json('docs')[0].id;
        apiHelper.get(`/pages/${firstId}`);
        thinkTime(1, 2);
      }

      const posts = apiHelper.get('/posts', { limit: 1, depth: 0 });
      if (posts.status === 200 && posts.json('totalDocs') > 0) {
        const firstId = posts.json('docs')[0].id;
        apiHelper.get(`/posts/${firstId}`);
        thinkTime(1, 2);
      }
    } catch (e) {
      // Items might not exist
      console.log('No items to view:', e.message);
    }
  });

  // Scenario 3: Create new content (write operations)
  group('Create Content', () => {
    // 20% chance to create a test post
    if (Math.random() < 0.2) {
      const newPost = {
        title: `Load Test Post ${testData.string(6)}`,
        content: testData.content(2),
        status: 'draft', // Save as draft to avoid publishing
      };

      const res = apiHelper.post('/posts', newPost);

      if (res.status === 201 || res.status === 200) {
        const postId = res.json('doc')?.id;

        // Store for potential cleanup (in real scenario)
        if (postId) {
          console.log(`Created post: ${postId}`);
        }
      }

      thinkTime(2, 3);
    }
  });

  // Scenario 4: Update content (write operations)
  group('Update Content', () => {
    // 30% chance to update a post
    if (Math.random() < 0.3) {
      try {
        // Get a random post
        const posts = apiHelper.get('/posts', { limit: 20, depth: 0, where: { status: { equals: 'draft' } } });

        if (posts.status === 200 && posts.json('totalDocs') > 0) {
          const docs = posts.json('docs');
          const randomPost = docs[Math.floor(Math.random() * docs.length)];
          const postId = randomPost.id;

          // Update the post
          const updateData = {
            title: `Updated ${randomPost.title}`,
          };

          apiHelper.put(`/posts/${postId}`, updateData);
          thinkTime(1, 2);
        }
      } catch (e) {
        console.log('Update failed:', e.message);
      }
    }
  });

  // Scenario 5: Delete test content (cleanup operations)
  group('Delete Content', () => {
    // 10% chance to delete a draft post
    if (Math.random() < 0.1) {
      try {
        // Get draft posts (likely from load test)
        const posts = apiHelper.get('/posts', {
          limit: 10,
          depth: 0,
          where: {
            status: { equals: 'draft' },
            title: { like: 'Load Test Post' },
          },
        });

        if (posts.status === 200 && posts.json('totalDocs') > 0) {
          const docs = posts.json('docs');
          const randomPost = docs[Math.floor(Math.random() * docs.length)];
          const postId = randomPost.id;

          // Delete the post
          apiHelper.delete(`/posts/${postId}`);
          thinkTime(1, 2);
        }
      } catch (e) {
        console.log('Delete failed:', e.message);
      }
    }
  });

  // Scenario 6: Use GraphQL API
  group('GraphQL Operations', () => {
    // 40% chance to use GraphQL
    if (Math.random() < 0.4) {
      const query = `
        query {
          Posts(limit: 5) {
            docs {
              id
              title
              status
            }
          }
        }
      `;

      apiHelper.graphql(query);
      thinkTime(1, 2);
    }
  });

  // Think time before next iteration
  thinkTime(3, 6);
}

/**
 * Teardown function - runs once after test
 */
export function teardown(data) {
  console.log('=== Admin Test Complete ===');
  console.log('Check results above for:');
  console.log('- p95 response time < 700ms');
  console.log('- Error rate < 1%');
  console.log('- 20 concurrent admin users sustained');
  console.log('Note: Any draft posts created were left in the system for manual review');
}
