/**
 * Approval Pipeline Test Helpers
 * 
 * Reusable helper functions for approval pipeline integration tests.
 * These helpers abstract common patterns for submission creation, approval,
 * and verification across all entity types.
 */

import { supabase } from '@/lib/supabaseClient';
import { TestDataTracker } from '../TestDataTracker';
import { formatTestError } from '../formatTestError';
import {
  submitParkCreation, 
  submitRideCreation,
  submitManufacturerCreation,
  submitOperatorCreation,
  submitDesignerCreation,
  submitPropertyOwnerCreation,
  submitRideModelCreation
} from '@/lib/entitySubmissionHelpers';

// Re-export formatTestError for use in test suites
export { formatTestError } from '../formatTestError';

// ============================================
// AUTHENTICATION
// ============================================

/**
 * Get current user auth token for edge function calls
 */
export async function getAuthToken(): Promise<string> {
  const { data: { session }, error } = await supabase.auth.getSession();
  if (error || !session) {
    throw new Error('Not authenticated - cannot run approval tests');
  }
  return session.access_token;
}

/**
 * Get current user ID
 */
export async function getCurrentUserId(): Promise<string> {
  const { data: { user }, error } = await supabase.auth.getUser();
  if (error || !user) {
    throw new Error('Not authenticated - cannot get user ID');
  }
  return user.id;
}

// ============================================
// EDGE FUNCTION CONFIGURATION
// ============================================

/**
 * Get edge function base URL (hardcoded per project requirements)
 */
export function getEdgeFunctionUrl(): string {
  return 'https://api.thrillwiki.com/functions/v1';
}

/**
 * Get Supabase anon key (hardcoded per project requirements)
 */
export function getSupabaseAnonKey(): string {
  return 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImRka2VueWdwcHlzZ3NlcmJ5aW9hIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Mjg0ODY0MTIsImV4cCI6MjA0NDA2MjQxMn0.0qfDbOvh-Hs5n7HHZ0cRQzH5oEL_1D7kj7v6nh4PqgI';
}

// ============================================
// TEST DATA GENERATORS
// ============================================

/**
 * Generate unique park submission data
 */
export function generateUniqueParkData(testId: string): any {
  const timestamp = Date.now();
  const slug = `test-park-${testId}-${timestamp}`;
  
  return {
    name: `Test Park ${testId} ${timestamp}`,
    slug,
    description: `Test park for ${testId}`,
    park_type: 'theme_park',
    status: 'operating',
    opening_date: '2000-01-01',
    opening_date_precision: 'year',
    location: {
      name: 'Test Location',
      city: 'Test City',
      country: 'US',
      latitude: 40.7128,
      longitude: -74.0060,
    },
    is_test_data: true,
  };
}

/**
 * Generate unique ride submission data
 */
export function generateUniqueRideData(parkId: string, testId: string): any {
  const timestamp = Date.now();
  const slug = `test-ride-${testId}-${timestamp}`;
  
  return {
    name: `Test Ride ${testId} ${timestamp}`,
    slug,
    description: `Test ride for ${testId}`,
    category: 'roller_coaster',
    status: 'operating',
    park_id: parkId,
    opening_date: '2005-01-01',
    opening_date_precision: 'year',
    max_speed_kmh: 100,
    max_height_meters: 50,
    length_meters: 1000,
    is_test_data: true,
  };
}

/**
 * Generate unique company submission data
 */
export function generateUniqueCompanyData(companyType: string, testId: string): any {
  const timestamp = Date.now();
  const slug = `test-${companyType}-${testId}-${timestamp}`;
  
  return {
    name: `Test ${companyType} ${testId} ${timestamp}`,
    slug,
    description: `Test ${companyType} for ${testId}`,
    person_type: 'company',
    founded_year: 1990,
    is_test_data: true,
  };
}

/**
 * Generate unique ride model submission data
 */
export function generateUniqueRideModelData(manufacturerId: string, testId: string): any {
  const timestamp = Date.now();
  const slug = `test-model-${testId}-${timestamp}`;
  
  return {
    name: `Test Model ${testId} ${timestamp}`,
    slug,
    manufacturer_id: manufacturerId,
    category: 'roller_coaster',
    ride_type: 'steel',
    description: `Test ride model for ${testId}`,
    is_test_data: true,
  };
}

// ============================================
// SUBMISSION CREATION HELPERS
// ============================================

/**
 * Create a test park submission
 */
export async function createTestParkSubmission(
  data: any,
  userId: string,
  tracker: TestDataTracker
): Promise<{ submissionId: string; itemId: string }> {
  const result = await submitParkCreation(data, userId);
  
  if (!result.submissionId) {
    throw new Error('Park submission creation failed - no submission ID returned');
  }
  
  // Track submission for cleanup
  tracker.track('content_submissions', result.submissionId);
  
  // Get the submission item ID
  const { data: items } = await supabase
    .from('submission_items')
    .select('id')
    .eq('submission_id', result.submissionId)
    .single();
  
  if (!items?.id) {
    throw new Error('Failed to get submission item ID');
  }
  
  tracker.track('submission_items', items.id);
  
  return {
    submissionId: result.submissionId,
    itemId: items.id,
  };
}

/**
 * Create a test ride submission
 */
export async function createTestRideSubmission(
  data: any,
  userId: string,
  tracker: TestDataTracker
): Promise<{ submissionId: string; itemId: string }> {
  const result = await submitRideCreation(data, userId);
  
  if (!result.submissionId) {
    throw new Error('Ride submission creation failed - no submission ID returned');
  }
  
  tracker.track('content_submissions', result.submissionId);
  
  const { data: items } = await supabase
    .from('submission_items')
    .select('id')
    .eq('submission_id', result.submissionId)
    .single();
  
  if (!items?.id) {
    throw new Error('Failed to get submission item ID');
  }
  
  tracker.track('submission_items', items.id);
  
  return {
    submissionId: result.submissionId,
    itemId: items.id,
  };
}

/**
 * Create a test company submission
 */
export async function createTestCompanySubmission(
  companyType: 'manufacturer' | 'operator' | 'designer' | 'property_owner',
  data: any,
  userId: string,
  tracker: TestDataTracker
): Promise<{ submissionId: string; itemId: string }> {
  // Call the appropriate company type-specific submission function
  let result: { submitted: boolean; submissionId: string };
  
  switch (companyType) {
    case 'manufacturer':
      result = await submitManufacturerCreation(data, userId);
      break;
    case 'operator':
      result = await submitOperatorCreation(data, userId);
      break;
    case 'designer':
      result = await submitDesignerCreation(data, userId);
      break;
    case 'property_owner':
      result = await submitPropertyOwnerCreation(data, userId);
      break;
    default:
      throw new Error(`Unknown company type: ${companyType}`);
  }
  
  if (!result.submissionId) {
    throw new Error('Company submission creation failed - no submission ID returned');
  }
  
  tracker.track('content_submissions', result.submissionId);
  
  const { data: items } = await supabase
    .from('submission_items')
    .select('id')
    .eq('submission_id', result.submissionId)
    .single();
  
  if (!items?.id) {
    throw new Error('Failed to get submission item ID');
  }
  
  tracker.track('submission_items', items.id);
  
  return {
    submissionId: result.submissionId,
    itemId: items.id,
  };
}

/**
 * Create a test ride model submission
 */
export async function createTestRideModelSubmission(
  data: any,
  userId: string,
  tracker: TestDataTracker
): Promise<{ submissionId: string; itemId: string }> {
  const result = await submitRideModelCreation(data, userId);
  
  if (!result.submissionId) {
    throw new Error('Ride model submission creation failed - no submission ID returned');
  }
  
  tracker.track('content_submissions', result.submissionId);
  
  const { data: items } = await supabase
    .from('submission_items')
    .select('id')
    .eq('submission_id', result.submissionId)
    .single();
  
  if (!items?.id) {
    throw new Error('Failed to get submission item ID');
  }
  
  tracker.track('submission_items', items.id);
  
  return {
    submissionId: result.submissionId,
    itemId: items.id,
  };
}

/**
 * Create a composite submission with dependencies
 */
export async function createCompositeSubmission(
  primaryEntity: { type: 'park' | 'ride'; data: any },
  dependencies: Array<{ type: string; data: any; tempId: string; companyType?: string }>,
  userId: string,
  tracker: TestDataTracker
): Promise<{ submissionId: string; itemIds: string[] }> {
  // Create main submission
  const { data: submission, error: submissionError } = await supabase
    .from('content_submissions')
    .insert({
      user_id: userId,
      submission_type: primaryEntity.type === 'park' ? 'park' : 'ride',
      status: 'pending',
      is_test_data: true,
    })
    .select()
    .single();
  
  if (submissionError || !submission) {
    throw new Error(`Failed to create submission: ${submissionError?.message}`);
  }
  
  tracker.track('content_submissions', submission.id);
  
  const itemIds: string[] = [];
  
  // Note: This is a simplified composite submission creation
  // In reality, the actual implementation uses specialized submission tables
  // (park_submissions, company_submissions, etc.) which are more complex
  // For testing purposes, we'll track items but note this is incomplete
  
  // Track submission for cleanup
  itemIds.push(submission.id);
  
  return {
    submissionId: submission.id,
    itemIds,
  };
}

// ============================================
// APPROVAL INVOCATION
// ============================================

/**
 * Approve submission via edge function
 */
export async function approveSubmission(
  submissionId: string,
  itemIds: string[],
  authToken: string,
  idempotencyKey?: string
): Promise<{
  success: boolean;
  status?: string;
  error?: string;
  duration: number;
}> {
  const startTime = performance.now();
  
  const key = idempotencyKey || `test-${Date.now()}-${Math.random()}`;
  
  try {
    const response = await fetch(
      `${getEdgeFunctionUrl()}/process-selective-approval`,
      {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${authToken}`,
          'Content-Type': 'application/json',
          'apikey': getSupabaseAnonKey(),
        },
        body: JSON.stringify({
          submissionId,
          itemIds,
          idempotencyKey: key,
        }),
      }
    );
    
    const duration = performance.now() - startTime;
    
    if (!response.ok) {
      const errorText = await response.text();
      return {
        success: false,
        error: `HTTP ${response.status}: ${errorText}`,
        duration,
      };
    }
    
    const result = await response.json();
    
    return {
      success: true,
      status: result.status || 'approved',
      duration,
    };
  } catch (error) {
    const duration = performance.now() - startTime;
    return {
      success: false,
      error: formatTestError(error),
      duration,
    };
  }
}

// ============================================
// POLLING & VERIFICATION
// ============================================

/**
 * Poll for entity creation
 */
export async function pollForEntity(
  table: 'parks' | 'rides' | 'companies' | 'ride_models',
  id: string,
  maxWaitMs: number = 10000
): Promise<any | null> {
  const pollInterval = 200;
  const startTime = Date.now();
  
  while (Date.now() - startTime < maxWaitMs) {
    const { data, error } = await supabase
      .from(table)
      .select('*')
      .eq('id', id)
      .single();
    
    if (data && !error) {
      return data;
    }
    
    await new Promise(resolve => setTimeout(resolve, pollInterval));
  }
  
  return null;
}

/**
 * Poll for version creation
 */
export async function pollForVersion(
  entityType: 'park' | 'ride' | 'company' | 'ride_model',
  entityId: string,
  expectedVersionNumber: number,
  maxWaitMs: number = 10000
): Promise<any | null> {
  const versionTable = `${entityType}_versions` as 'park_versions' | 'ride_versions' | 'company_versions' | 'ride_model_versions';
  const pollInterval = 200;
  const startTime = Date.now();
  
  while (Date.now() - startTime < maxWaitMs) {
    const { data, error } = await supabase
      .from(versionTable)
      .select('*')
      .eq(`${entityType}_id`, entityId)
      .eq('version_number', expectedVersionNumber)
      .single();
    
    if (data && !error) {
      return data;
    }
    
    await new Promise(resolve => setTimeout(resolve, pollInterval));
  }
  
  return null;
}

/**
 * Verify submission item is approved
 */
export async function verifySubmissionItemApproved(
  itemId: string
): Promise<{ approved: boolean; entityId: string | null; error?: string }> {
  const { data, error } = await supabase
    .from('submission_items')
    .select('status, approved_entity_id')
    .eq('id', itemId)
    .single();
  
  if (error) {
    return { approved: false, entityId: null, error: error.message };
  }
  
  return {
    approved: data.status === 'approved' && !!data.approved_entity_id,
    entityId: data.approved_entity_id,
  };
}

/**
 * Verify submission status
 */
export async function verifySubmissionStatus(
  submissionId: string,
  expectedStatus: 'approved' | 'partially_approved' | 'pending'
): Promise<boolean> {
  const { data, error } = await supabase
    .from('content_submissions')
    .select('status')
    .eq('id', submissionId)
    .single();
  
  if (error || !data) {
    return false;
  }
  
  return data.status === expectedStatus;
}

/**
 * Create entity directly (bypass moderation for setup)
 */
export async function createParkDirectly(
  data: any,
  tracker: TestDataTracker
): Promise<string> {
  // First create location if provided
  let locationId: string | undefined;
  
  if (data.location) {
    const { data: location, error: locError } = await supabase
      .from('locations')
      .insert({
        name: data.location.name,
        city: data.location.city,
        country: data.location.country,
        latitude: data.location.latitude,
        longitude: data.location.longitude,
      })
      .select()
      .single();
    
    if (locError || !location) {
      throw new Error(`Failed to create location: ${locError?.message}`);
    }
    
    locationId = location.id;
    tracker.track('locations', locationId);
  }
  
  const parkData = { ...data };
  delete parkData.location;
  if (locationId) {
    parkData.location_id = locationId;
  }
  
  const { data: park, error } = await supabase
    .from('parks')
    .insert(parkData)
    .select()
    .single();
  
  if (error || !park) {
    throw new Error(`Failed to create park directly: ${error?.message}`);
  }
  
  tracker.track('parks', park.id);
  return park.id;
}

/**
 * Create ride directly (bypass moderation for setup)
 */
export async function createRideDirectly(
  data: any,
  tracker: TestDataTracker
): Promise<string> {
  const { data: ride, error } = await supabase
    .from('rides')
    .insert(data)
    .select()
    .single();
  
  if (error || !ride) {
    throw new Error(`Failed to create ride directly: ${error?.message}`);
  }
  
  tracker.track('rides', ride.id);
  return ride.id;
}

/**
 * Create test photo gallery submission
 */
export async function createTestPhotoGallerySubmission(
  entityId: string,
  entityType: 'park' | 'ride',
  photoCount: number,
  userId: string,
  tracker: TestDataTracker
): Promise<{ submissionId: string; itemId: string }> {
  // Create content submission first
  const { data: submission, error: submissionError } = await supabase
    .from('content_submissions')
    .insert({
      user_id: userId,
      submission_type: 'photo_gallery',
      status: 'pending',
      is_test_data: true,
    })
    .select()
    .single();
  
  if (submissionError || !submission) {
    throw new Error(`Failed to create content submission: ${submissionError?.message}`);
  }
  
  tracker.track('content_submissions', submission.id);
  
  // Create photo submission
  const { data: photoSubmission, error: photoSubError } = await supabase
    .from('photo_submissions')
    .insert({
      entity_id: entityId,
      entity_type: entityType,
      submission_id: submission.id,
      is_test_data: true,
    })
    .select()
    .single();
  
  if (photoSubError || !photoSubmission) {
    throw new Error(`Failed to create photo submission: ${photoSubError?.message}`);
  }
  
  tracker.track('photo_submissions', photoSubmission.id);
  
  // Create submission item linking to photo submission
  const { data: item, error: itemError } = await supabase
    .from('submission_items')
    .insert({
      submission_id: submission.id,
      photo_submission_id: photoSubmission.id,
      item_type: 'photo_gallery',
      status: 'pending',
      is_test_data: true,
    })
    .select()
    .single();
  
  if (itemError || !item) {
    throw new Error(`Failed to create submission item: ${itemError?.message}`);
  }
  
  tracker.track('submission_items', item.id);
  
  // Create photo submission items
  for (let i = 0; i < photoCount; i++) {
    const { data: photoItem, error: photoItemError } = await supabase
      .from('photo_submission_items')
      .insert({
        photo_submission_id: photoSubmission.id,
        cloudflare_image_id: `test-image-${Date.now()}-${i}`,
        cloudflare_image_url: `https://test.com/image-${i}.jpg`,
        caption: `Test photo ${i + 1}`,
        order_index: i,
        is_test_data: true,
      })
      .select()
      .single();
    
    if (photoItemError || !photoItem) {
      throw new Error(`Failed to create photo item ${i}: ${photoItemError?.message}`);
    }
    
    tracker.track('photo_submission_items', photoItem.id);
  }
  
  return {
    submissionId: submission.id,
    itemId: item.id,
  };
}
