// tests/api/01-generation-basic.ts
// Basic Image Generation Tests - Run FIRST to verify core functionality

import { api, log, runTest, saveImage, waitForGeneration, testContext, verifyImageAccessible, exitWithTestResults } from './utils';
import { endpoints } from './config';

async function main() {
  log.section('GENERATION BASIC TESTS');

  // Test 1: Simple generation without references
  await runTest('Generate image - simple prompt', async () => {
    const result = await api(endpoints.generations, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        prompt: 'A beautiful sunset over mountains',
        aspectRatio: '16:9',
      }),
    });

    if (!result.data.data || !result.data.data.id) {
      throw new Error('No generation returned');
    }

    testContext.basicGenerationId = result.data.data.id;
    log.detail('Generation ID', result.data.data.id);
    log.detail('Status', result.data.data.status);

    // Wait for completion
    log.info('Waiting for generation to complete...');
    const generation = await waitForGeneration(testContext.basicGenerationId);

    if (generation.status !== 'success') {
      throw new Error(`Generation failed: ${generation.errorMessage}`);
    }

    if (!generation.outputImageId) {
      throw new Error('No output image ID');
    }

    log.detail('Processing time', `${generation.processingTimeMs}ms`);
    log.detail('Output image ID', generation.outputImageId);

    // Verify image exists and is accessible
    const imageResult = await api(`${endpoints.images}/${generation.outputImageId}`);
    const imageUrl = imageResult.data.data.storageUrl;

    const accessible = await verifyImageAccessible(imageUrl);
    if (!accessible) {
      throw new Error('Generated image not accessible');
    }

    // Save for manual inspection
    const imageResponse = await fetch(imageUrl);
    const imageBuffer = await imageResponse.arrayBuffer();
    await saveImage(imageBuffer, 'gen-basic-simple.png');

    testContext.basicOutputImageId = generation.outputImageId;
  });

  // Test 2: Generation with aspect ratio 1:1
  await runTest('Generate image - square (1:1)', async () => {
    const result = await api(endpoints.generations, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        prompt: 'A minimalist logo design',
        aspectRatio: '1:1',
      }),
    });

    const generation = await waitForGeneration(result.data.data.id);

    if (generation.status !== 'success') {
      throw new Error(`Generation failed: ${generation.errorMessage}`);
    }

    log.detail('Output image', generation.outputImageId);
  });

  // Test 3: Generation with aspect ratio 9:16 (portrait)
  await runTest('Generate image - portrait (9:16)', async () => {
    const result = await api(endpoints.generations, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        prompt: 'A tall building at night',
        aspectRatio: '9:16',
      }),
    });

    const generation = await waitForGeneration(result.data.data.id);

    if (generation.status !== 'success') {
      throw new Error(`Generation failed: ${generation.errorMessage}`);
    }

    log.detail('Aspect ratio', '9:16');
    log.detail('Output image', generation.outputImageId);
  });

  // Test 4: Get generation details
  await runTest('Get generation by ID', async () => {
    const result = await api(`${endpoints.generations}/${testContext.basicGenerationId}`);

    if (!result.data.data) {
      throw new Error('Generation not found');
    }

    const generation = result.data.data;

    // Verify all expected fields present
    if (!generation.id) throw new Error('Missing id');
    if (!generation.prompt) throw new Error('Missing prompt');
    if (!generation.status) throw new Error('Missing status');
    if (!generation.outputImageId) throw new Error('Missing outputImageId');
    if (!generation.createdAt) throw new Error('Missing createdAt');

    log.detail('Generation ID', generation.id);
    log.detail('Prompt', generation.prompt);
    log.detail('Status', generation.status);
    log.detail('Has output image', !!generation.outputImage);
  });

  // Test 5: List generations
  await runTest('List all generations', async () => {
    const result = await api(endpoints.generations);

    if (!result.data.data || !Array.isArray(result.data.data)) {
      throw new Error('No generations array returned');
    }

    log.detail('Total generations', result.data.data.length);

    // Verify our generation is in the list
    const found = result.data.data.find((g: any) => g.id === testContext.basicGenerationId);
    if (!found) {
      throw new Error('Created generation not in list');
    }

    log.detail('Found our generation', '✓');
    log.detail('Successful generations', result.data.data.filter((g: any) => g.status === 'success').length);
  });

  // Test 6: List generations with pagination
  await runTest('List generations with pagination', async () => {
    const result = await api(`${endpoints.generations}?limit=2&offset=0`);

    if (!result.data.data || !Array.isArray(result.data.data)) {
      throw new Error('No generations array returned');
    }

    if (!result.data.pagination) {
      throw new Error('No pagination data');
    }

    log.detail('Limit', result.data.pagination.limit);
    log.detail('Offset', result.data.pagination.offset);
    log.detail('Total', result.data.pagination.total);
    log.detail('Has more', result.data.pagination.hasMore);

    // Results should be limited
    if (result.data.data.length > 2) {
      throw new Error('Pagination limit not applied');
    }
  });

  // Test 7: List generations with status filter
  await runTest('List generations - filter by status', async () => {
    const result = await api(`${endpoints.generations}?status=success`);

    if (!result.data.data || !Array.isArray(result.data.data)) {
      throw new Error('No generations array returned');
    }

    // All results should have success status
    const allSuccess = result.data.data.every((g: any) => g.status === 'success');
    if (!allSuccess) {
      throw new Error('Status filter not working');
    }

    log.detail('Success generations', result.data.data.length);
  });

  // Test 8: Generation processing time is recorded
  await runTest('Verify processing time recorded', async () => {
    const result = await api(`${endpoints.generations}/${testContext.basicGenerationId}`);
    const generation = result.data.data;

    if (typeof generation.processingTimeMs !== 'number') {
      throw new Error('Processing time not recorded');
    }

    if (generation.processingTimeMs <= 0) {
      throw new Error('Processing time should be positive');
    }

    log.detail('Processing time', `${generation.processingTimeMs}ms`);
    log.detail('Approximately', `${(generation.processingTimeMs / 1000).toFixed(2)}s`);
  });

  log.section('GENERATION BASIC TESTS COMPLETED');
}

main()
  .then(() => exitWithTestResults())
  .catch((error) => {
    console.error('Unexpected error:', error);
    process.exit(1);
  });
