/**
 * Approval Pipeline Integration Test Suite
 * 
 * Comprehensive end-to-end tests for the submission approval workflow.
 * Tests the complete pipeline: Form → Submission → Moderation → Edge Function → RPC → Entity Creation → Versioning
 * 
 * Coverage:
 * - Single entity creation (parks, rides, companies, ride models)
 * - Entity updates through pipeline
 * - Composite submissions with temp references
 * - Photo gallery submissions
 * - Edge cases (partial approval, idempotency, locks, invalid refs, banned users)
 * - Versioning integrity
 */

import type { Test, TestSuite, TestResult } from '../testRunner';
import { TestDataTracker } from '../TestDataTracker';
import { supabase } from '@/lib/supabaseClient';
import {
  getAuthToken,
  getCurrentUserId,
  generateUniqueParkData,
  generateUniqueRideData,
  generateUniqueCompanyData,
  generateUniqueRideModelData,
  createTestParkSubmission,
  createTestRideSubmission,
  createTestCompanySubmission,
  createTestRideModelSubmission,
  createCompositeSubmission,
  createTestPhotoGallerySubmission,
  approveSubmission,
  pollForEntity,
  pollForVersion,
  verifySubmissionItemApproved,
  verifySubmissionStatus,
  createParkDirectly,
  createRideDirectly,
  formatTestError,
} from '../helpers/approvalTestHelpers';

// ============================================
// CATEGORY 1: SINGLE ENTITY CREATION TESTS
// ============================================

/**
 * APL-001: Park Creation Through Full Pipeline
 */
const parkCreationTest: Test = {
  id: 'APL-001',
  name: 'Park Creation Through Full Pipeline',
  description: 'Validates park creation from submission to entity with versioning',
  run: async (): Promise<TestResult> => {
    const startTime = Date.now();
    const tracker = new TestDataTracker();
    
    try {
      // 1. Setup
      const userId = await getCurrentUserId();
      const authToken = await getAuthToken();
      const parkData = generateUniqueParkData('apl-001');
      
      // 2. Create submission
      const { submissionId, itemId } = await createTestParkSubmission(parkData, userId, tracker);
      
      // 3. Verify submission created
      const { data: submission } = await supabase
        .from('content_submissions')
        .select('*')
        .eq('id', submissionId)
        .single();
      
      if (!submission || submission.status !== 'pending') {
        throw new Error('Submission not created with pending status');
      }
      
      // 4. Approve submission
      const approvalResult = await approveSubmission(submissionId, [itemId], authToken);
      
      if (!approvalResult.success) {
        throw new Error(`Approval failed: ${approvalResult.error}`);
      }
      
      // 5. Poll for park creation
      const park = await pollForEntity('parks', parkData.slug, 10000);
      
      if (!park) {
        throw new Error('Park not created within timeout');
      }
      
      tracker.track('parks', park.id);
      
      // 6. Verify park data
      if (park.name !== parkData.name || park.slug !== parkData.slug) {
        throw new Error('Park data mismatch');
      }
      
      // 7. Poll for version
      const version = await pollForVersion('park', park.id, 1, 10000);
      
      if (!version) {
        throw new Error('Park version not created');
      }
      
      tracker.track('park_versions', version.id);
      
      // 8. Verify submission item approved
      const itemCheck = await verifySubmissionItemApproved(itemId);
      
      if (!itemCheck.approved || itemCheck.entityId !== park.id) {
        throw new Error('Submission item not properly approved');
      }
      
      // 9. Verify submission status
      const statusCheck = await verifySubmissionStatus(submissionId, 'approved');
      
      if (!statusCheck) {
        throw new Error('Submission status not updated to approved');
      }
      
      return {
        id: 'APL-001',
        name: 'Park Creation Through Full Pipeline',
        suite: 'Approval Pipeline',
        status: 'pass',
        duration: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      };
    } catch (error) {
      return {
        id: 'APL-001',
        name: 'Park Creation Through Full Pipeline',
        suite: 'Approval Pipeline',
        status: 'fail',
        duration: Date.now() - startTime,
        error: formatTestError(error),
        stack: error instanceof Error ? error.stack : undefined,
        timestamp: new Date().toISOString(),
      };
    } finally {
      await tracker.cleanup();
    }
  },
};

/**
 * APL-002: Ride Creation Through Full Pipeline
 */
const rideCreationTest: Test = {
  id: 'APL-002',
  name: 'Ride Creation Through Full Pipeline',
  description: 'Validates ride creation with park relationship',
  run: async (): Promise<TestResult> => {
    const startTime = Date.now();
    const tracker = new TestDataTracker();
    
    try {
      const userId = await getCurrentUserId();
      const authToken = await getAuthToken();
      
      // Create test park first
      const parkData = generateUniqueParkData('apl-002-park');
      const parkId = await createParkDirectly(parkData, tracker);
      
      // Wait for park version
      await pollForVersion('park', parkId, 1, 10000);
      
      // Create ride submission
      const rideData = generateUniqueRideData(parkId, 'apl-002');
      const { submissionId, itemId } = await createTestRideSubmission(rideData, userId, tracker);
      
      // Approve
      const approvalResult = await approveSubmission(submissionId, [itemId], authToken);
      
      if (!approvalResult.success) {
        throw new Error(`Approval failed: ${approvalResult.error}`);
      }
      
      // Poll for ride
      const ride = await pollForEntity('rides', rideData.slug, 10000);
      
      if (!ride) {
        throw new Error('Ride not created within timeout');
      }
      
      tracker.track('rides', ride.id);
      
      // Verify park relationship
      if (ride.park_id !== parkId) {
        throw new Error('Ride park_id mismatch');
      }
      
      // Verify version
      const version = await pollForVersion('ride', ride.id, 1, 10000);
      
      if (!version) {
        throw new Error('Ride version not created');
      }
      
      tracker.track('ride_versions', version.id);
      
      // Verify approval
      const itemCheck = await verifySubmissionItemApproved(itemId);
      
      if (!itemCheck.approved || itemCheck.entityId !== ride.id) {
        throw new Error('Submission item not properly approved');
      }
      
      return {
        id: 'APL-002',
        name: 'Ride Creation Through Full Pipeline',
        suite: 'Approval Pipeline',
        status: 'pass',
        duration: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      };
    } catch (error) {
      return {
        id: 'APL-002',
        name: 'Ride Creation Through Full Pipeline',
        suite: 'Approval Pipeline',
        status: 'fail',
        duration: Date.now() - startTime,
        error: formatTestError(error),
        stack: error instanceof Error ? error.stack : undefined,
        timestamp: new Date().toISOString(),
      };
    } finally {
      await tracker.cleanup();
    }
  },
};

/**
 * APL-003: Company Creation (All 4 Types)
 */
const companyCreationTest: Test = {
  id: 'APL-003',
  name: 'Company Creation (All 4 Types)',
  description: 'Validates all company types: manufacturer, operator, designer, property_owner',
  run: async (): Promise<TestResult> => {
    const startTime = Date.now();
    const tracker = new TestDataTracker();
    
    try {
      const userId = await getCurrentUserId();
      const authToken = await getAuthToken();
      
      const companyTypes = ['manufacturer', 'operator', 'designer', 'property_owner'] as const;
      
      for (const companyType of companyTypes) {
        const companyData = generateUniqueCompanyData(companyType, `apl-003-${companyType}`);
        
        const { submissionId, itemId } = await createTestCompanySubmission(
          companyType,
          companyData,
          userId,
          tracker
        );
        
        const approvalResult = await approveSubmission(submissionId, [itemId], authToken);
        
        if (!approvalResult.success) {
          throw new Error(`${companyType} approval failed: ${approvalResult.error}`);
        }
        
        const company = await pollForEntity('companies', companyData.slug, 10000);
        
        if (!company) {
          throw new Error(`${companyType} not created within timeout`);
        }
        
        tracker.track('companies', company.id);
        
        // Note: company_type is stored via RPC during approval process
        // We verify the company was created successfully
        
        const version = await pollForVersion('company', company.id, 1, 10000);
        
        if (!version) {
          throw new Error(`${companyType} version not created`);
        }
        
        tracker.track('company_versions', version.id);
      }
      
      return {
        id: 'APL-003',
        name: 'Company Creation (All 4 Types)',
        suite: 'Approval Pipeline',
        status: 'pass',
        duration: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      };
    } catch (error) {
      return {
        id: 'APL-003',
        name: 'Company Creation (All 4 Types)',
        suite: 'Approval Pipeline',
        status: 'fail',
        duration: Date.now() - startTime,
        error: formatTestError(error),
        stack: error instanceof Error ? error.stack : undefined,
        timestamp: new Date().toISOString(),
      };
    } finally {
      await tracker.cleanup();
    }
  },
};

/**
 * APL-004: Ride Model Creation
 */
const rideModelCreationTest: Test = {
  id: 'APL-004',
  name: 'Ride Model Creation',
  description: 'Validates ride model creation with manufacturer relationship',
  run: async (): Promise<TestResult> => {
    const startTime = Date.now();
    const tracker = new TestDataTracker();
    
    try {
      const userId = await getCurrentUserId();
      const authToken = await getAuthToken();
      
      // Create manufacturer first
      const manufacturerData = generateUniqueCompanyData('manufacturer', 'apl-004-mfg');
      const { submissionId: mfgSubId, itemId: mfgItemId } = await createTestCompanySubmission(
        'manufacturer',
        manufacturerData,
        userId,
        tracker
      );
      
      await approveSubmission(mfgSubId, [mfgItemId], authToken);
      
      const manufacturer = await pollForEntity('companies', manufacturerData.slug, 10000);
      
      if (!manufacturer) {
        throw new Error('Manufacturer not created');
      }
      
      tracker.track('companies', manufacturer.id);
      
      // Create ride model
      const modelData = generateUniqueRideModelData(manufacturer.id, 'apl-004');
      const { submissionId, itemId } = await createTestRideModelSubmission(modelData, userId, tracker);
      
      const approvalResult = await approveSubmission(submissionId, [itemId], authToken);
      
      if (!approvalResult.success) {
        throw new Error(`Approval failed: ${approvalResult.error}`);
      }
      
      const model = await pollForEntity('ride_models', modelData.slug, 10000);
      
      if (!model) {
        throw new Error('Ride model not created within timeout');
      }
      
      tracker.track('ride_models', model.id);
      
      if (model.manufacturer_id !== manufacturer.id) {
        throw new Error('Ride model manufacturer_id mismatch');
      }
      
      const version = await pollForVersion('ride_model', model.id, 1, 10000);
      
      if (!version) {
        throw new Error('Ride model version not created');
      }
      
      tracker.track('ride_model_versions', version.id);
      
      return {
        id: 'APL-004',
        name: 'Ride Model Creation',
        suite: 'Approval Pipeline',
        status: 'pass',
        duration: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      };
    } catch (error) {
      return {
        id: 'APL-004',
        name: 'Ride Model Creation',
        suite: 'Approval Pipeline',
        status: 'fail',
        duration: Date.now() - startTime,
        error: formatTestError(error),
        stack: error instanceof Error ? error.stack : undefined,
        timestamp: new Date().toISOString(),
      };
    } finally {
      await tracker.cleanup();
    }
  },
};

// ============================================
// CATEGORY 2: COMPOSITE SUBMISSION TESTS
// ============================================

/**
 * APL-007: Ride + Manufacturer Composite
 */
const rideManufacturerCompositeTest: Test = {
  id: 'APL-007',
  name: 'Ride + Manufacturer Composite',
  description: 'Validates composite submission with temp manufacturer reference',
  run: async (): Promise<TestResult> => {
    const startTime = Date.now();
    const tracker = new TestDataTracker();
    
    try {
      const userId = await getCurrentUserId();
      const authToken = await getAuthToken();
      
      // Create park first
      const parkData = generateUniqueParkData('apl-007-park');
      const parkId = await createParkDirectly(parkData, tracker);
      
      // Create composite submission
      const manufacturerData = generateUniqueCompanyData('manufacturer', 'apl-007-mfg');
      const rideData = generateUniqueRideData(parkId, 'apl-007');
      
      const { submissionId, itemIds } = await createCompositeSubmission(
        {
          type: 'ride',
          data: rideData,
        },
        [
          {
            type: 'company',
            data: manufacturerData,
            tempId: 'temp-manufacturer',
            companyType: 'manufacturer',
          },
        ],
        userId,
        tracker
      );
      
      // Note: Temp refs are stored in specialized submission tables (ride_submissions)
      // not in submission_items.item_data. This test validates the resolution works.
      
      // Approve all
      const approvalResult = await approveSubmission(submissionId, itemIds, authToken);
      
      if (!approvalResult.success) {
        throw new Error(`Approval failed: ${approvalResult.error}`);
      }
      
      // Poll for manufacturer
      const manufacturer = await pollForEntity('companies', manufacturerData.slug, 10000);
      
      if (!manufacturer) {
        throw new Error('Manufacturer not created');
      }
      
      tracker.track('companies', manufacturer.id);
      
      // Poll for ride
      const ride = await pollForEntity('rides', rideData.slug, 10000);
      
      if (!ride) {
        throw new Error('Ride not created');
      }
      
      tracker.track('rides', ride.id);
      
      // Verify temp ref resolved
      if (ride.manufacturer_id !== manufacturer.id) {
        throw new Error('Temp manufacturer ref not resolved correctly');
      }
      
      // Verify both items approved
      const mfgCheck = await verifySubmissionItemApproved(itemIds[0]);
      const rideCheck = await verifySubmissionItemApproved(itemIds[1]);
      
      if (!mfgCheck.approved || !rideCheck.approved) {
        throw new Error('Not all items approved');
      }
      
      return {
        id: 'APL-007',
        name: 'Ride + Manufacturer Composite',
        suite: 'Approval Pipeline',
        status: 'pass',
        duration: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      };
    } catch (error) {
      return {
        id: 'APL-007',
        name: 'Ride + Manufacturer Composite',
        suite: 'Approval Pipeline',
        status: 'fail',
        duration: Date.now() - startTime,
        error: formatTestError(error),
        stack: error instanceof Error ? error.stack : undefined,
        timestamp: new Date().toISOString(),
      };
    } finally {
      await tracker.cleanup();
    }
  },
};

/**
 * APL-012: Partial Approval
 */
const partialApprovalTest: Test = {
  id: 'APL-012',
  name: 'Partial Approval',
  description: 'Validates partial approval workflow',
  run: async (): Promise<TestResult> => {
    const startTime = Date.now();
    const tracker = new TestDataTracker();
    
    try {
      const userId = await getCurrentUserId();
      const authToken = await getAuthToken();
      
      // Create composite with 3 items
      const operatorData = generateUniqueCompanyData('operator', 'apl-012-op');
      const ownerData = generateUniqueCompanyData('property_owner', 'apl-012-owner');
      const parkData = generateUniqueParkData('apl-012');
      
      const { submissionId, itemIds } = await createCompositeSubmission(
        {
          type: 'park',
          data: parkData,
        },
        [
          {
            type: 'company',
            data: operatorData,
            tempId: 'temp-operator',
            companyType: 'operator',
          },
          {
            type: 'company',
            data: ownerData,
            tempId: 'temp-owner',
            companyType: 'property_owner',
          },
        ],
        userId,
        tracker
      );
      
      // Approve only first 2 items (companies, not park)
      const approvalResult = await approveSubmission(submissionId, itemIds.slice(0, 2), authToken);
      
      if (!approvalResult.success) {
        throw new Error(`Partial approval failed: ${approvalResult.error}`);
      }
      
      // Verify companies created
      const operator = await pollForEntity('companies', operatorData.slug, 10000);
      const owner = await pollForEntity('companies', ownerData.slug, 10000);
      
      if (!operator || !owner) {
        throw new Error('Companies not created');
      }
      
      tracker.track('companies', operator.id);
      tracker.track('companies', owner.id);
      
      // Verify park NOT created
      const park = await pollForEntity('parks', parkData.slug, 2000);
      
      if (park) {
        throw new Error('Park should not be created in partial approval');
      }
      
      // Verify submission status
      const statusCheck = await verifySubmissionStatus(submissionId, 'partially_approved');
      
      if (!statusCheck) {
        throw new Error('Submission should be partially_approved');
      }
      
      // Now approve the park
      const secondApprovalResult = await approveSubmission(submissionId, [itemIds[2]], authToken);
      
      if (!secondApprovalResult.success) {
        throw new Error(`Second approval failed: ${secondApprovalResult.error}`);
      }
      
      // Verify park created with correct refs
      const parkNow = await pollForEntity('parks', parkData.slug, 10000);
      
      if (!parkNow) {
        throw new Error('Park not created after second approval');
      }
      
      tracker.track('parks', parkNow.id);
      
      if (parkNow.operator_id !== operator.id || parkNow.property_owner_id !== owner.id) {
        throw new Error('Park company refs not resolved correctly');
      }
      
      // Verify final status
      const finalStatusCheck = await verifySubmissionStatus(submissionId, 'approved');
      
      if (!finalStatusCheck) {
        throw new Error('Submission should be fully approved now');
      }
      
      return {
        id: 'APL-012',
        name: 'Partial Approval',
        suite: 'Approval Pipeline',
        status: 'pass',
        duration: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      };
    } catch (error) {
      return {
        id: 'APL-012',
        name: 'Partial Approval',
        suite: 'Approval Pipeline',
        status: 'fail',
        duration: Date.now() - startTime,
        error: formatTestError(error),
        stack: error instanceof Error ? error.stack : undefined,
        timestamp: new Date().toISOString(),
      };
    } finally {
      await tracker.cleanup();
    }
  },
};

/**
 * APL-013: Idempotency Key Handling
 */
const idempotencyTest: Test = {
  id: 'APL-013',
  name: 'Idempotency Key Handling',
  description: 'Validates idempotency prevents duplicate approvals',
  run: async (): Promise<TestResult> => {
    const startTime = Date.now();
    const tracker = new TestDataTracker();
    
    try {
      const userId = await getCurrentUserId();
      const authToken = await getAuthToken();
      
      const parkData = generateUniqueParkData('apl-013');
      const { submissionId, itemId } = await createTestParkSubmission(parkData, userId, tracker);
      
      // Generate unique idempotency key
      const idempotencyKey = `test-idempotency-${Date.now()}`;
      
      // First approval
      const firstResult = await approveSubmission(submissionId, [itemId], authToken, idempotencyKey);
      
      if (!firstResult.success) {
        throw new Error(`First approval failed: ${firstResult.error}`);
      }
      
      // Wait for completion
      const park = await pollForEntity('parks', parkData.slug, 10000);
      
      if (!park) {
        throw new Error('Park not created');
      }
      
      tracker.track('parks', park.id);
      
      // Second approval with same key
      const secondResult = await approveSubmission(submissionId, [itemId], authToken, idempotencyKey);
      
      if (!secondResult.success) {
        throw new Error(`Second approval should succeed with cached result: ${secondResult.error}`);
      }
      
      // Verify only 1 park exists
      const { count } = await supabase
        .from('parks')
        .select('*', { count: 'exact', head: true })
        .eq('slug', parkData.slug);
      
      if (count !== 1) {
        throw new Error(`Expected 1 park, found ${count}`);
      }
      
      // Verify idempotency key record exists
      const { data: keyRecord } = await supabase
        .from('submission_idempotency_keys')
        .select('*')
        .eq('idempotency_key', idempotencyKey)
        .single();
      
      if (!keyRecord || keyRecord.status !== 'completed') {
        throw new Error('Idempotency key not recorded correctly');
      }
      
      return {
        id: 'APL-013',
        name: 'Idempotency Key Handling',
        suite: 'Approval Pipeline',
        status: 'pass',
        duration: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      };
    } catch (error) {
      return {
        id: 'APL-013',
        name: 'Idempotency Key Handling',
        suite: 'Approval Pipeline',
        status: 'fail',
        duration: Date.now() - startTime,
        error: formatTestError(error),
        stack: error instanceof Error ? error.stack : undefined,
        timestamp: new Date().toISOString(),
      };
    } finally {
      await tracker.cleanup();
    }
  },
};

/**
 * APL-005: Park Update Through Pipeline
 */
const parkUpdateTest: Test = {
  id: 'APL-005',
  name: 'Park Update Through Pipeline',
  description: 'Validates park updates create new versions',
  run: async (): Promise<TestResult> => {
    const startTime = Date.now();
    const tracker = new TestDataTracker();
    
    try {
      const userId = await getCurrentUserId();
      const authToken = await getAuthToken();
      
      // Create park directly
      const parkData = generateUniqueParkData('apl-005');
      const parkId = await createParkDirectly(parkData, tracker);
      
      // Wait for version 1
      const version1 = await pollForVersion('park', parkId, 1, 10000);
      if (!version1) {
        throw new Error('Version 1 not created');
      }
      tracker.track('park_versions', version1.id);
      
      // Submit update
      const updateData = {
        ...parkData,
        name: `${parkData.name} UPDATED`,
        description: 'Updated description',
      };
      
      const { submissionId, itemId } = await createTestParkSubmission(updateData, userId, tracker);
      
      // Approve update
      const approvalResult = await approveSubmission(submissionId, [itemId], authToken);
      if (!approvalResult.success) {
        throw new Error(`Update approval failed: ${approvalResult.error}`);
      }
      
      // Wait for version 2
      const version2 = await pollForVersion('park', parkId, 2, 10000);
      if (!version2) {
        throw new Error('Version 2 not created after update');
      }
      tracker.track('park_versions', version2.id);
      
      // Verify park updated
      const { data: updatedPark } = await supabase
        .from('parks')
        .select('*')
        .eq('id', parkId)
        .single();
      
      if (!updatedPark || !updatedPark.name.includes('UPDATED')) {
        throw new Error('Park not updated correctly');
      }
      
      // Verify version 1 still exists with original data
      const { data: v1Check } = await supabase
        .from('park_versions')
        .select('*')
        .eq('id', version1.id)
        .single();
      
      if (!v1Check || v1Check.version_number !== 1) {
        throw new Error('Version 1 corrupted');
      }
      
      return {
        id: 'APL-005',
        name: 'Park Update Through Pipeline',
        suite: 'Approval Pipeline',
        status: 'pass',
        duration: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      };
    } catch (error) {
      return {
        id: 'APL-005',
        name: 'Park Update Through Pipeline',
        suite: 'Approval Pipeline',
        status: 'fail',
        duration: Date.now() - startTime,
        error: formatTestError(error),
        stack: error instanceof Error ? error.stack : undefined,
        timestamp: new Date().toISOString(),
      };
    } finally {
      await tracker.cleanup();
    }
  },
};

/**
 * APL-006: Ride Update Through Pipeline
 */
const rideUpdateTest: Test = {
  id: 'APL-006',
  name: 'Ride Update Through Pipeline',
  description: 'Validates ride updates create new versions',
  run: async (): Promise<TestResult> => {
    const startTime = Date.now();
    const tracker = new TestDataTracker();
    
    try {
      const userId = await getCurrentUserId();
      const authToken = await getAuthToken();
      
      // Create park first
      const parkData = generateUniqueParkData('apl-006-park');
      const parkId = await createParkDirectly(parkData, tracker);
      
      // Create ride directly
      const rideData = generateUniqueRideData(parkId, 'apl-006');
      const rideId = await createRideDirectly(rideData, tracker);
      
      // Wait for version 1
      const version1 = await pollForVersion('ride', rideId, 1, 10000);
      if (!version1) {
        throw new Error('Version 1 not created');
      }
      tracker.track('ride_versions', version1.id);
      
      // Submit update
      const updateData = {
        ...rideData,
        name: `${rideData.name} UPDATED`,
        max_speed_kmh: 120,
      };
      
      const { submissionId, itemId } = await createTestRideSubmission(updateData, userId, tracker);
      
      // Approve update
      const approvalResult = await approveSubmission(submissionId, [itemId], authToken);
      if (!approvalResult.success) {
        throw new Error(`Update approval failed: ${approvalResult.error}`);
      }
      
      // Wait for version 2
      const version2 = await pollForVersion('ride', rideId, 2, 10000);
      if (!version2) {
        throw new Error('Version 2 not created after update');
      }
      tracker.track('ride_versions', version2.id);
      
      // Verify ride updated
      const { data: updatedRide } = await supabase
        .from('rides')
        .select('*')
        .eq('id', rideId)
        .single();
      
      if (!updatedRide || !updatedRide.name.includes('UPDATED') || updatedRide.max_speed_kmh !== 120) {
        throw new Error('Ride not updated correctly');
      }
      
      return {
        id: 'APL-006',
        name: 'Ride Update Through Pipeline',
        suite: 'Approval Pipeline',
        status: 'pass',
        duration: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      };
    } catch (error) {
      return {
        id: 'APL-006',
        name: 'Ride Update Through Pipeline',
        suite: 'Approval Pipeline',
        status: 'fail',
        duration: Date.now() - startTime,
        error: formatTestError(error),
        stack: error instanceof Error ? error.stack : undefined,
        timestamp: new Date().toISOString(),
      };
    } finally {
      await tracker.cleanup();
    }
  },
};

/**
 * APL-008: Ride + Manufacturer + Designer Composite
 */
const rideManufacturerDesignerCompositeTest: Test = {
  id: 'APL-008',
  name: 'Ride + Manufacturer + Designer Composite',
  description: 'Validates composite with multiple company temp references',
  run: async (): Promise<TestResult> => {
    const startTime = Date.now();
    const tracker = new TestDataTracker();
    
    try {
      const userId = await getCurrentUserId();
      const authToken = await getAuthToken();
      
      // Create park
      const parkData = generateUniqueParkData('apl-008-park');
      const parkId = await createParkDirectly(parkData, tracker);
      
      // Create composite
      const manufacturerData = generateUniqueCompanyData('manufacturer', 'apl-008-mfg');
      const designerData = generateUniqueCompanyData('designer', 'apl-008-des');
      const rideData = generateUniqueRideData(parkId, 'apl-008');
      
      const { submissionId, itemIds } = await createCompositeSubmission(
        {
          type: 'ride',
          data: rideData,
        },
        [
          {
            type: 'company',
            data: manufacturerData,
            tempId: 'temp-manufacturer',
            companyType: 'manufacturer',
          },
          {
            type: 'company',
            data: designerData,
            tempId: 'temp-designer',
            companyType: 'designer',
          },
        ],
        userId,
        tracker
      );
      
      // Approve all
      const approvalResult = await approveSubmission(submissionId, itemIds, authToken);
      if (!approvalResult.success) {
        throw new Error(`Approval failed: ${approvalResult.error}`);
      }
      
      // Poll for companies
      const manufacturer = await pollForEntity('companies', manufacturerData.slug, 10000);
      const designer = await pollForEntity('companies', designerData.slug, 10000);
      
      if (!manufacturer || !designer) {
        throw new Error('Companies not created');
      }
      
      tracker.track('companies', manufacturer.id);
      tracker.track('companies', designer.id);
      
      // Poll for ride
      const ride = await pollForEntity('rides', rideData.slug, 10000);
      if (!ride) {
        throw new Error('Ride not created');
      }
      
      tracker.track('rides', ride.id);
      
      // Verify both temp refs resolved
      if (ride.manufacturer_id !== manufacturer.id || ride.designer_id !== designer.id) {
        throw new Error('Temp refs not resolved correctly');
      }
      
      return {
        id: 'APL-008',
        name: 'Ride + Manufacturer + Designer Composite',
        suite: 'Approval Pipeline',
        status: 'pass',
        duration: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      };
    } catch (error) {
      return {
        id: 'APL-008',
        name: 'Ride + Manufacturer + Designer Composite',
        suite: 'Approval Pipeline',
        status: 'fail',
        duration: Date.now() - startTime,
        error: formatTestError(error),
        stack: error instanceof Error ? error.stack : undefined,
        timestamp: new Date().toISOString(),
      };
    } finally {
      await tracker.cleanup();
    }
  },
};

/**
 * APL-009: Park + Operator + Property Owner Composite
 */
const parkOperatorOwnerCompositeTest: Test = {
  id: 'APL-009',
  name: 'Park + Operator + Property Owner Composite',
  description: 'Validates park composite with operator and owner temp references',
  run: async (): Promise<TestResult> => {
    const startTime = Date.now();
    const tracker = new TestDataTracker();
    
    try {
      const userId = await getCurrentUserId();
      const authToken = await getAuthToken();
      
      // Create composite
      const operatorData = generateUniqueCompanyData('operator', 'apl-009-op');
      const ownerData = generateUniqueCompanyData('property_owner', 'apl-009-owner');
      const parkData = generateUniqueParkData('apl-009');
      
      const { submissionId, itemIds } = await createCompositeSubmission(
        {
          type: 'park',
          data: parkData,
        },
        [
          {
            type: 'company',
            data: operatorData,
            tempId: 'temp-operator',
            companyType: 'operator',
          },
          {
            type: 'company',
            data: ownerData,
            tempId: 'temp-owner',
            companyType: 'property_owner',
          },
        ],
        userId,
        tracker
      );
      
      // Approve all
      const approvalResult = await approveSubmission(submissionId, itemIds, authToken);
      if (!approvalResult.success) {
        throw new Error(`Approval failed: ${approvalResult.error}`);
      }
      
      // Poll for companies
      const operator = await pollForEntity('companies', operatorData.slug, 10000);
      const owner = await pollForEntity('companies', ownerData.slug, 10000);
      
      if (!operator || !owner) {
        throw new Error('Companies not created');
      }
      
      tracker.track('companies', operator.id);
      tracker.track('companies', owner.id);
      
      // Poll for park
      const park = await pollForEntity('parks', parkData.slug, 10000);
      if (!park) {
        throw new Error('Park not created');
      }
      
      tracker.track('parks', park.id);
      
      // Verify temp refs resolved
      if (park.operator_id !== operator.id || park.property_owner_id !== owner.id) {
        throw new Error('Park company refs not resolved correctly');
      }
      
      return {
        id: 'APL-009',
        name: 'Park + Operator + Property Owner Composite',
        suite: 'Approval Pipeline',
        status: 'pass',
        duration: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      };
    } catch (error) {
      return {
        id: 'APL-009',
        name: 'Park + Operator + Property Owner Composite',
        suite: 'Approval Pipeline',
        status: 'fail',
        duration: Date.now() - startTime,
        error: formatTestError(error),
        stack: error instanceof Error ? error.stack : undefined,
        timestamp: new Date().toISOString(),
      };
    } finally {
      await tracker.cleanup();
    }
  },
};

/**
 * APL-014: Lock Conflict Prevention
 */
const lockConflictTest: Test = {
  id: 'APL-014',
  name: 'Lock Conflict Prevention',
  description: 'Validates locked submissions prevent concurrent approval',
  run: async (): Promise<TestResult> => {
    const startTime = Date.now();
    const tracker = new TestDataTracker();
    
    try {
      const userId = await getCurrentUserId();
      const authToken = await getAuthToken();
      
      // Create submission 1 - same user lock (should succeed)
      const parkData1 = generateUniqueParkData('apl-014-a');
      const { submissionId: subId1, itemId: itemId1 } = await createTestParkSubmission(parkData1, userId, tracker);
      
      // Lock to current user
      await supabase
        .from('content_submissions')
        .update({
          assigned_to: userId,
          locked_until: new Date(Date.now() + 15 * 60 * 1000).toISOString(),
        })
        .eq('id', subId1);
      
      // Approve (should succeed - same user)
      const result1 = await approveSubmission(subId1, [itemId1], authToken);
      if (!result1.success) {
        throw new Error(`Same user approval should succeed: ${result1.error}`);
      }
      
      const park1 = await pollForEntity('parks', parkData1.slug, 10000);
      if (!park1) {
        throw new Error('Park 1 not created');
      }
      tracker.track('parks', park1.id);
      
      // Create submission 2 - different user lock (should fail)
      const parkData2 = generateUniqueParkData('apl-014-b');
      const { submissionId: subId2, itemId: itemId2 } = await createTestParkSubmission(parkData2, userId, tracker);
      
      // Lock to fake user
      const fakeUserId = '00000000-0000-0000-0000-000000000001';
      await supabase
        .from('content_submissions')
        .update({
          assigned_to: fakeUserId,
          locked_until: new Date(Date.now() + 15 * 60 * 1000).toISOString(),
        })
        .eq('id', subId2);
      
      // Try to approve (should fail)
      const result2 = await approveSubmission(subId2, [itemId2], authToken);
      if (result2.success) {
        throw new Error('Approval should fail when locked by different user');
      }
      
      // Verify park NOT created
      const park2 = await pollForEntity('parks', parkData2.slug, 2000);
      if (park2) {
        throw new Error('Park 2 should not be created due to lock');
      }
      
      return {
        id: 'APL-014',
        name: 'Lock Conflict Prevention',
        suite: 'Approval Pipeline',
        status: 'pass',
        duration: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      };
    } catch (error) {
      return {
        id: 'APL-014',
        name: 'Lock Conflict Prevention',
        suite: 'Approval Pipeline',
        status: 'fail',
        duration: Date.now() - startTime,
        error: formatTestError(error),
        stack: error instanceof Error ? error.stack : undefined,
        timestamp: new Date().toISOString(),
      };
    } finally {
      await tracker.cleanup();
    }
  },
};

/**
 * APL-016: Banned User Rejection
 */
const bannedUserTest: Test = {
  id: 'APL-016',
  name: 'Banned User Rejection',
  description: 'Validates banned users cannot have submissions approved',
  run: async (): Promise<TestResult> => {
    const startTime = Date.now();
    const tracker = new TestDataTracker();
    
    try {
      const userId = await getCurrentUserId();
      const authToken = await getAuthToken();
      
      // Create submission
      const parkData = generateUniqueParkData('apl-016');
      const { submissionId, itemId } = await createTestParkSubmission(parkData, userId, tracker);
      
      // Ban user
      await supabase
        .from('profiles')
        .update({ banned: true })
        .eq('user_id', userId);
      
      // Try to approve (should fail)
      const result = await approveSubmission(submissionId, [itemId], authToken);
      if (result.success) {
        throw new Error('Approval should fail for banned user');
      }
      
      // Verify park NOT created
      const park = await pollForEntity('parks', parkData.slug, 2000);
      if (park) {
        throw new Error('Park should not be created for banned user');
      }
      
      // Unban user
      await supabase
        .from('profiles')
        .update({ banned: false })
        .eq('user_id', userId);
      
      // Try again (should succeed now)
      const result2 = await approveSubmission(submissionId, [itemId], authToken);
      if (!result2.success) {
        throw new Error(`Approval should succeed after unban: ${result2.error}`);
      }
      
      // Verify park created
      const parkNow = await pollForEntity('parks', parkData.slug, 10000);
      if (!parkNow) {
        throw new Error('Park not created after unban');
      }
      tracker.track('parks', parkNow.id);
      
      return {
        id: 'APL-016',
        name: 'Banned User Rejection',
        suite: 'Approval Pipeline',
        status: 'pass',
        duration: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      };
    } catch (error) {
      // Make sure to unban user even if test fails
      try {
        const userId = await getCurrentUserId();
        await supabase
          .from('profiles')
          .update({ banned: false })
          .eq('user_id', userId);
      } catch (cleanupError) {
        console.error('Failed to unban user in cleanup:', cleanupError);
      }
      
      return {
        id: 'APL-016',
        name: 'Banned User Rejection',
        suite: 'Approval Pipeline',
        status: 'fail',
        duration: Date.now() - startTime,
        error: formatTestError(error),
        stack: error instanceof Error ? error.stack : undefined,
        timestamp: new Date().toISOString(),
      };
    } finally {
      await tracker.cleanup();
    }
  },
};

/**
 * APL-017: Multiple Edit Chain
 */
const multipleEditChainTest: Test = {
  id: 'APL-017',
  name: 'Multiple Edit Chain',
  description: 'Validates multiple sequential edits create correct version chain',
  run: async (): Promise<TestResult> => {
    const startTime = Date.now();
    const tracker = new TestDataTracker();
    
    try {
      const userId = await getCurrentUserId();
      const authToken = await getAuthToken();
      
      // Create park directly
      const parkData = generateUniqueParkData('apl-017');
      const parkId = await createParkDirectly(parkData, tracker);
      
      // Wait for version 1
      await pollForVersion('park', parkId, 1, 10000);
      
      // Edit 1: Change name
      const edit1Data = { ...parkData, name: `${parkData.name} V2` };
      const { submissionId: sub1, itemId: item1 } = await createTestParkSubmission(edit1Data, userId, tracker);
      await approveSubmission(sub1, [item1], authToken);
      const v2 = await pollForVersion('park', parkId, 2, 10000);
      if (!v2) throw new Error('Version 2 not created');
      tracker.track('park_versions', v2.id);
      
      // Edit 2: Change description
      const edit2Data = { ...edit1Data, description: 'Version 3 description' };
      const { submissionId: sub2, itemId: item2 } = await createTestParkSubmission(edit2Data, userId, tracker);
      await approveSubmission(sub2, [item2], authToken);
      const v3 = await pollForVersion('park', parkId, 3, 10000);
      if (!v3) throw new Error('Version 3 not created');
      tracker.track('park_versions', v3.id);
      
      // Edit 3: Change status
      const edit3Data = { ...edit2Data, status: 'closed' };
      const { submissionId: sub3, itemId: item3 } = await createTestParkSubmission(edit3Data, userId, tracker);
      await approveSubmission(sub3, [item3], authToken);
      const v4 = await pollForVersion('park', parkId, 4, 10000);
      if (!v4) throw new Error('Version 4 not created');
      tracker.track('park_versions', v4.id);
      
      // Verify all 4 versions exist
      const { count } = await supabase
        .from('park_versions')
        .select('*', { count: 'exact', head: true })
        .eq('park_id', parkId);
      
      if (count !== 4) {
        throw new Error(`Expected 4 versions, found ${count}`);
      }
      
      // Verify version numbers are correct
      const { data: versions } = await supabase
        .from('park_versions')
        .select('version_number')
        .eq('park_id', parkId)
        .order('version_number', { ascending: true });
      
      const versionNumbers = versions?.map(v => v.version_number) || [];
      if (versionNumbers.join(',') !== '1,2,3,4') {
        throw new Error(`Version sequence incorrect: ${versionNumbers.join(',')}`);
      }
      
      return {
        id: 'APL-017',
        name: 'Multiple Edit Chain',
        suite: 'Approval Pipeline',
        status: 'pass',
        duration: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      };
    } catch (error) {
      return {
        id: 'APL-017',
        name: 'Multiple Edit Chain',
        suite: 'Approval Pipeline',
        status: 'fail',
        duration: Date.now() - startTime,
        error: formatTestError(error),
        stack: error instanceof Error ? error.stack : undefined,
        timestamp: new Date().toISOString(),
      };
    } finally {
      await tracker.cleanup();
    }
  },
};

/**
 * APL-019: Version Snapshot Integrity
 */
const versionSnapshotIntegrityTest: Test = {
  id: 'APL-019',
  name: 'Version Snapshot Integrity',
  description: 'Validates version snapshots maintain data integrity',
  run: async (): Promise<TestResult> => {
    const startTime = Date.now();
    const tracker = new TestDataTracker();
    
    try {
      const userId = await getCurrentUserId();
      const authToken = await getAuthToken();
      
      // Create park with all fields
      const parkData = generateUniqueParkData('apl-019');
      const fullParkData = {
        ...parkData,
        description: 'Full description with all fields',
        website_url: 'https://example.com',
        phone: '+1234567890',
        email: 'test@example.com',
      };
      
      const parkId = await createParkDirectly(fullParkData, tracker);
      
      // Wait for version 1
      const v1 = await pollForVersion('park', parkId, 1, 10000);
      if (!v1) throw new Error('Version 1 not created');
      tracker.track('park_versions', v1.id);
      
      // Update only 2 fields
      const updateData = {
        ...fullParkData,
        name: `${fullParkData.name} CHANGED`,
        description: 'Updated description only',
      };
      
      const { submissionId, itemId } = await createTestParkSubmission(updateData, userId, tracker);
      await approveSubmission(submissionId, [itemId], authToken);
      
      // Wait for version 2
      const v2 = await pollForVersion('park', parkId, 2, 10000);
      if (!v2) throw new Error('Version 2 not created');
      tracker.track('park_versions', v2.id);
      
      // Verify version 1 has original values
      const { data: version1 } = await supabase
        .from('park_versions')
        .select('*')
        .eq('id', v1.id)
        .single();
      
      if (!version1 || version1.name !== fullParkData.name) {
        throw new Error('Version 1 data corrupted');
      }
      
      if (version1.website_url !== fullParkData.website_url) {
        throw new Error('Version 1 unchanged fields corrupted');
      }
      
      // Verify version 2 has updated values
      const { data: version2 } = await supabase
        .from('park_versions')
        .select('*')
        .eq('id', v2.id)
        .single();
      
      if (!version2 || !version2.name.includes('CHANGED')) {
        throw new Error('Version 2 changes not captured');
      }
      
      // Verify unchanged fields identical in both versions
      if (version1.website_url !== version2.website_url || 
          version1.phone !== version2.phone ||
          version1.email !== version2.email) {
        throw new Error('Unchanged fields differ between versions');
      }
      
      return {
        id: 'APL-019',
        name: 'Version Snapshot Integrity',
        suite: 'Approval Pipeline',
        status: 'pass',
        duration: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      };
    } catch (error) {
      return {
        id: 'APL-019',
        name: 'Version Snapshot Integrity',
        suite: 'Approval Pipeline',
        status: 'fail',
        duration: Date.now() - startTime,
        error: formatTestError(error),
        stack: error instanceof Error ? error.stack : undefined,
        timestamp: new Date().toISOString(),
      };
    } finally {
      await tracker.cleanup();
    }
  },
};

/**
 * APL-010: Photo Gallery for Park
 */
const parkPhotoGalleryTest: Test = {
  id: 'APL-010',
  name: 'Photo Gallery for Park',
  description: 'Validates photo gallery submissions for parks',
  run: async (): Promise<TestResult> => {
    const startTime = Date.now();
    const tracker = new TestDataTracker();
    
    try {
      const userId = await getCurrentUserId();
      const authToken = await getAuthToken();
      
      // Create park
      const parkData = generateUniqueParkData('apl-010');
      const parkId = await createParkDirectly(parkData, tracker);
      
      // Create photo gallery submission
      const { submissionId, itemId } = await createTestPhotoGallerySubmission(
        parkId,
        'park',
        3,
        userId,
        tracker
      );
      
      // Approve
      const approvalResult = await approveSubmission(submissionId, [itemId], authToken);
      if (!approvalResult.success) {
        throw new Error(`Photo approval failed: ${approvalResult.error}`);
      }
      
      // Wait and verify photos created
      await new Promise(resolve => setTimeout(resolve, 2000));
      
      const { data: photos, error } = await supabase
        .from('photos')
        .select('*')
        .eq('entity_id', parkId)
        .eq('entity_type', 'park');
      
      if (error || !photos || photos.length !== 3) {
        throw new Error(`Expected 3 photos, found ${photos?.length || 0}`);
      }
      
      photos.forEach(photo => {
        tracker.track('photos', photo.id);
        if (photo.entity_id !== parkId || photo.entity_type !== 'park') {
          throw new Error('Photo entity references incorrect');
        }
      });
      
      return {
        id: 'APL-010',
        name: 'Photo Gallery for Park',
        suite: 'Approval Pipeline',
        status: 'pass',
        duration: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      };
    } catch (error) {
      return {
        id: 'APL-010',
        name: 'Photo Gallery for Park',
        suite: 'Approval Pipeline',
        status: 'fail',
        duration: Date.now() - startTime,
        error: formatTestError(error),
        stack: error instanceof Error ? error.stack : undefined,
        timestamp: new Date().toISOString(),
      };
    } finally {
      await tracker.cleanup();
    }
  },
};

/**
 * APL-011: Photo Gallery for Ride
 */
const ridePhotoGalleryTest: Test = {
  id: 'APL-011',
  name: 'Photo Gallery for Ride',
  description: 'Validates photo gallery submissions for rides',
  run: async (): Promise<TestResult> => {
    const startTime = Date.now();
    const tracker = new TestDataTracker();
    
    try {
      const userId = await getCurrentUserId();
      const authToken = await getAuthToken();
      
      // Create park and ride
      const parkData = generateUniqueParkData('apl-011-park');
      const parkId = await createParkDirectly(parkData, tracker);
      
      const rideData = generateUniqueRideData(parkId, 'apl-011');
      const rideId = await createRideDirectly(rideData, tracker);
      
      // Create photo gallery submission with 5 photos
      const { submissionId, itemId } = await createTestPhotoGallerySubmission(
        rideId,
        'ride',
        5,
        userId,
        tracker
      );
      
      // Approve
      const approvalResult = await approveSubmission(submissionId, [itemId], authToken);
      if (!approvalResult.success) {
        throw new Error(`Photo approval failed: ${approvalResult.error}`);
      }
      
      // Wait and verify photos created
      await new Promise(resolve => setTimeout(resolve, 2000));
      
      const { data: photos, error } = await supabase
        .from('photos')
        .select('*')
        .eq('entity_id', rideId)
        .eq('entity_type', 'ride');
      
      if (error || !photos || photos.length !== 5) {
        throw new Error(`Expected 5 photos, found ${photos?.length || 0}`);
      }
      
      photos.forEach(photo => {
        tracker.track('photos', photo.id);
        if (photo.entity_id !== rideId || photo.entity_type !== 'ride') {
          throw new Error('Photo entity references incorrect');
        }
      });
      
      return {
        id: 'APL-011',
        name: 'Photo Gallery for Ride',
        suite: 'Approval Pipeline',
        status: 'pass',
        duration: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      };
    } catch (error) {
      return {
        id: 'APL-011',
        name: 'Photo Gallery for Ride',
        suite: 'Approval Pipeline',
        status: 'fail',
        duration: Date.now() - startTime,
        error: formatTestError(error),
        stack: error instanceof Error ? error.stack : undefined,
        timestamp: new Date().toISOString(),
      };
    } finally {
      await tracker.cleanup();
    }
  },
};

/**
 * APL-015: Invalid Temp Reference Rejection
 */
const invalidTempRefTest: Test = {
  id: 'APL-015',
  name: 'Invalid Temp Reference Rejection',
  description: 'Validates submissions with invalid temp references are rejected',
  run: async (): Promise<TestResult> => {
    const startTime = Date.now();
    const tracker = new TestDataTracker();
    
    try {
      const userId = await getCurrentUserId();
      const authToken = await getAuthToken();
      
      // Create park
      const parkData = generateUniqueParkData('apl-015-park');
      const parkId = await createParkDirectly(parkData, tracker);
      
      // Create ride submission manually with invalid temp ref
      const rideData = generateUniqueRideData(parkId, 'apl-015');
      
      // Create submission
      const { data: submission, error: subError } = await supabase
        .from('content_submissions')
        .insert({
          user_id: userId,
          submission_type: 'ride_create',
          status: 'pending',
          is_test_data: true,
        })
        .select()
        .single();
      
      if (subError || !submission) {
        throw new Error('Failed to create test submission');
      }
      
      tracker.track('content_submissions', submission.id);
      
      // Create ride submission with invalid temp ref (99 doesn't exist)
      const { data: rideSubmission, error: rideSubError } = await supabase
        .from('ride_submissions')
        .insert({
          ...rideData,
          _temp_manufacturer_ref: 99, // Invalid - no item with this order_index
          is_test_data: true,
        })
        .select()
        .single();
      
      if (rideSubError || !rideSubmission) {
        throw new Error('Failed to create ride submission');
      }
      
      tracker.track('ride_submissions', rideSubmission.id);
      
      // Create submission item
      const { data: item, error: itemError } = await supabase
        .from('submission_items')
        .insert({
          submission_id: submission.id,
          ride_submission_id: rideSubmission.id,
          item_type: 'ride_create',
          status: 'pending',
          is_test_data: true,
        })
        .select()
        .single();
      
      if (itemError || !item) {
        throw new Error('Failed to create submission item');
      }
      
      tracker.track('submission_items', item.id);
      
      // Try to approve (should fail)
      const approvalResult = await approveSubmission(submission.id, [item.id], authToken);
      
      if (approvalResult.success) {
        throw new Error('Approval should fail with invalid temp ref');
      }
      
      // Verify ride NOT created
      const ride = await pollForEntity('rides', rideData.slug, 2000);
      if (ride) {
        throw new Error('Ride should not be created with invalid temp ref');
      }
      
      return {
        id: 'APL-015',
        name: 'Invalid Temp Reference Rejection',
        suite: 'Approval Pipeline',
        status: 'pass',
        duration: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      };
    } catch (error) {
      return {
        id: 'APL-015',
        name: 'Invalid Temp Reference Rejection',
        suite: 'Approval Pipeline',
        status: 'fail',
        duration: Date.now() - startTime,
        error: formatTestError(error),
        stack: error instanceof Error ? error.stack : undefined,
        timestamp: new Date().toISOString(),
      };
    } finally {
      await tracker.cleanup();
    }
  },
};

/**
 * APL-018: Concurrent Edit Conflict
 */
const concurrentEditTest: Test = {
  id: 'APL-018',
  name: 'Concurrent Edit Conflict',
  description: 'Validates concurrent edits are applied in order',
  run: async (): Promise<TestResult> => {
    const startTime = Date.now();
    const tracker = new TestDataTracker();
    
    try {
      const userId = await getCurrentUserId();
      const authToken = await getAuthToken();
      
      // Create park
      const parkData = generateUniqueParkData('apl-018');
      const parkId = await createParkDirectly(parkData, tracker);
      
      // Wait for version 1
      await pollForVersion('park', parkId, 1, 10000);
      
      // Create two concurrent edits
      const editA = { ...parkData, name: `${parkData.name} NAME-A` };
      const editB = { ...parkData, name: `${parkData.name} NAME-B` };
      
      const { submissionId: subA, itemId: itemA } = await createTestParkSubmission(editA, userId, tracker);
      const { submissionId: subB, itemId: itemB } = await createTestParkSubmission(editB, userId, tracker);
      
      // Approve edit A first
      await approveSubmission(subA, [itemA], authToken);
      const v2 = await pollForVersion('park', parkId, 2, 10000);
      if (!v2) throw new Error('Version 2 not created');
      tracker.track('park_versions', v2.id);
      
      // Then approve edit B
      await approveSubmission(subB, [itemB], authToken);
      const v3 = await pollForVersion('park', parkId, 3, 10000);
      if (!v3) throw new Error('Version 3 not created');
      tracker.track('park_versions', v3.id);
      
      // Verify final park name is NAME-B (last edit wins)
      const { data: finalPark } = await supabase
        .from('parks')
        .select('name')
        .eq('id', parkId)
        .single();
      
      if (!finalPark || !finalPark.name.includes('NAME-B')) {
        throw new Error(`Expected NAME-B, got ${finalPark?.name}`);
      }
      
      // Verify version 2 has NAME-A
      const { data: v2Check } = await supabase
        .from('park_versions')
        .select('name')
        .eq('id', v2.id)
        .single();
      
      if (!v2Check || !v2Check.name.includes('NAME-A')) {
        throw new Error('Version 2 should have NAME-A');
      }
      
      // Verify version 3 has NAME-B
      const { data: v3Check } = await supabase
        .from('park_versions')
        .select('name')
        .eq('id', v3.id)
        .single();
      
      if (!v3Check || !v3Check.name.includes('NAME-B')) {
        throw new Error('Version 3 should have NAME-B');
      }
      
      return {
        id: 'APL-018',
        name: 'Concurrent Edit Conflict',
        suite: 'Approval Pipeline',
        status: 'pass',
        duration: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      };
    } catch (error) {
      return {
        id: 'APL-018',
        name: 'Concurrent Edit Conflict',
        suite: 'Approval Pipeline',
        status: 'fail',
        duration: Date.now() - startTime,
        error: formatTestError(error),
        stack: error instanceof Error ? error.stack : undefined,
        timestamp: new Date().toISOString(),
      };
    } finally {
      await tracker.cleanup();
    }
  },
};

// ============================================
// TEST SUITE EXPORT
// ============================================

export const approvalPipelineTestSuite: TestSuite = {
  id: 'approval-pipeline',
  name: 'Approval Pipeline Integration',
  description: 'End-to-end tests for submission approval workflow through edge functions and RPC',
  tests: [
    parkCreationTest,
    rideCreationTest,
    companyCreationTest,
    rideModelCreationTest,
    parkUpdateTest,
    rideUpdateTest,
    rideManufacturerCompositeTest,
    rideManufacturerDesignerCompositeTest,
    parkOperatorOwnerCompositeTest,
    parkPhotoGalleryTest,
    ridePhotoGalleryTest,
    partialApprovalTest,
    idempotencyTest,
    lockConflictTest,
    invalidTempRefTest,
    bannedUserTest,
    multipleEditChainTest,
    concurrentEditTest,
    versionSnapshotIntegrityTest,
  ],
};
