/**
 * Integration tests for PostgreSQL persistence
 * Tests end-to-end database operations with real PostgreSQL connection
 * 
 * Prerequisites:
 * - Server must be running (via docker-compose or test setup)
 * - TEST_SERVER_URL environment variable set (default: http://localhost:3000)
 * - TEST_API_KEY environment variable set
 * - TEST_DATABASE_URL or DATABASE_URL pointing to PostgreSQL
 */

import { describe, it, expect, beforeAll } from '@jest/globals';
import {
  initTestServer,
  authenticatedRequest,
  waitForServer,
  getTestServerUrl,
} from './helpers/test-server';

describe('PostgreSQL Persistence Integration', () => {
  beforeAll(async () => {
    // Initialize test server config
    initTestServer();
    
    // Wait for server to be ready
    const isReady = await waitForServer(30000);
    if (!isReady) {
      throw new Error('Test server is not ready. Make sure the server is running.');
    }

    // Check if PostgreSQL is available
    const databaseUrl = process.env.TEST_DATABASE_URL || process.env.DATABASE_URL;
    
    if (!databaseUrl || !databaseUrl.includes('postgresql')) {
      console.warn('⚠️  Skipping PostgreSQL tests: TEST_DATABASE_URL not set or not PostgreSQL');
      // Skip all tests if PostgreSQL is not available
      return;
    }
  });

  describe('Run CRUD Operations', () => {
    it('should create a run and persist to PostgreSQL', async () => {
      const response = await authenticatedRequest('/api/runs', {
        method: 'POST',
        body: JSON.stringify({
          name: 'Integration Test Run',
          input: { test: 'data' },
        }),
      });

      expect(response.status).toBe(201);
      const data = await response.json();
      
      expect(data).toHaveProperty('success', true);
      expect(data).toHaveProperty('run');
      expect(data.run).toHaveProperty('id');
      expect(data.run).toHaveProperty('name', 'Integration Test Run');
      expect(['pending', 'created']).toContain(data.run.status);
      expect(data.run).toHaveProperty('input', { test: 'data' });
      expect(data.run).toHaveProperty('createdAt');
    });

    it('should retrieve a run from PostgreSQL', async () => {
      // First create a run
      const createResponse = await authenticatedRequest('/api/runs', {
        method: 'POST',
        body: JSON.stringify({
          name: 'Retrieval Test Run',
          input: { test: 'retrieval' },
        }),
      });

      const createData = await createResponse.json();
      const runId = createData.run.id;

      // Then retrieve it
      const getResponse = await authenticatedRequest(`/api/runs/${runId}`);

      expect(getResponse.status).toBe(200);
      const getData = await getResponse.json();
      
      // GET endpoint may return run directly or wrapped in { run: {...} }
      const run = getData.run || getData;
      expect(run.id).toBe(runId);
      expect(run.name).toBe('Retrieval Test Run');
    });

    it('should list runs from PostgreSQL', async () => {
      // Create a few runs
      for (let i = 0; i < 3; i++) {
        await authenticatedRequest('/api/runs', {
          method: 'POST',
          body: JSON.stringify({
            name: `List Test Run ${i}`,
            input: { index: i },
          }),
        });
      }

      // List runs
      const listResponse = await authenticatedRequest('/api/runs');

      expect(listResponse.status).toBe(200);
      const listData = await listResponse.json();
      
      expect(listData).toHaveProperty('runs');
      expect(Array.isArray(listData.runs)).toBe(true);
      expect(listData.runs.length).toBeGreaterThanOrEqual(3);
    });

    it('should update run status in PostgreSQL', async () => {
      // Create a run
      const createResponse = await authenticatedRequest('/api/runs', {
        method: 'POST',
        body: JSON.stringify({
          name: 'Update Test Run',
          input: { test: 'update' },
        }),
      });

      const createData = await createResponse.json();
      const runId = createData.run.id;

      // Start the run (which updates status)
      const startResponse = await authenticatedRequest(`/api/runs/${runId}/start`, {
        method: 'POST',
        body: JSON.stringify({
          priority: 'high',
        }),
      });

      expect(startResponse.status).toBe(200);

      // Verify status was updated
      const getResponse = await authenticatedRequest(`/api/runs/${runId}`);

      const getData = await getResponse.json();
      const run = getData.run || getData;
      expect(['queued', 'running', 'created', 'pending']).toContain(run.status);
    });
  });

  describe('Data Persistence', () => {
    it('should persist run data across server restarts', async () => {
      // Create a run
      const createResponse = await authenticatedRequest('/api/runs', {
        method: 'POST',
        body: JSON.stringify({
          name: 'Persistence Test Run',
          input: { persistent: true },
        }),
      });

      const createData = await createResponse.json();
      const runId = createData.run.id;

      // Note: In a real integration test, you would restart the server here
      // For now, we just verify the data was persisted
      // In CI/CD, you could restart the docker container and verify

      // Retrieve the run (assuming server was restarted)
      // In practice, you'd wait for server to be ready again
      const getResponse = await authenticatedRequest(`/api/runs/${runId}`);

      expect(getResponse.status).toBe(200);
      const getData = await getResponse.json();
      const run = getData.run || getData;
      expect(run.id).toBe(runId);
      expect(run.name).toBe('Persistence Test Run');
    });
  });
});

