import { supabase } from '@/integrations/supabase/client';
import type { Json } from '@/integrations/supabase/types';
import { ImageAssignments } from '@/components/upload/EntityMultiImageUploader';
import { uploadPendingImages } from './imageUploadHelper';
import type { ProcessedImage } from './supabaseHelpers';
import { extractChangedFields } from './submissionChangeDetection';
import type { CompanyDatabaseRecord, TimelineEventDatabaseRecord } from '@/types/company-data';
import { logger } from './logger';
import { getErrorMessage } from './errorHandler';
import type { TimelineEventFormData, EntityType } from '@/types/timeline';

// ============================================
// COMPOSITE SUBMISSION TYPES
// ============================================

interface CompositeSubmissionDependency {
  type: 'park' | 'ride' | 'company' | 'ride_model';
  data: any;
  tempId: string;
  companyType?: 'manufacturer' | 'designer' | 'operator' | 'property_owner';
  parentTempId?: string; // For linking ride_model to manufacturer
}

interface CompositeSubmissionData {
  primaryEntity: {
    type: 'park' | 'ride';
    data: any;
  };
  dependencies: CompositeSubmissionDependency[];
}

/**
 * ═══════════════════════════════════════════════════════════════════
 * SUBMISSION PATTERN STANDARD - CRITICAL PROJECT RULE
 * ═══════════════════════════════════════════════════════════════════
 * 
 * ⚠️ NEVER STORE JSON IN SQL COLUMNS ⚠️
 * 
 * content_submissions.content should ONLY contain:
 * ✅ action: 'create' | 'edit' | 'delete'
 * ✅ Minimal reference IDs (entity_id, parent_id, etc.) - MAX 3 fields
 * ❌ NO actual form data
 * ❌ NO submission content
 * ❌ NO large objects
 * 
 * ALL actual data MUST go in:
 * ✅ submission_items.item_data (new data)
 * ✅ submission_items.original_data (for edits)
 * ✅ Specialized relational tables:
 *    - photo_submissions + photo_submission_items
 *    - park_submissions
 *    - ride_submissions
 *    - company_submissions
 *    - ride_model_submissions
 * 
 * If your data is relational, model it relationally.
 * JSON blobs destroy:
 * - Queryability (can't filter/join)
 * - Performance (slower, larger)
 * - Data integrity (no constraints)
 * - Maintainability (impossible to refactor)
 * 
 * EXAMPLES:
 * 
 * ✅ CORRECT:
 * content: { action: 'create' }
 * content: { action: 'edit', park_id: uuid }
 * content: { action: 'delete', photo_id: uuid }
 * 
 * ❌ WRONG:
 * content: { name: '...', description: '...', ...formData }
 * content: { photos: [...], metadata: {...} }
 * content: data  // entire object dump
 * 
 * ═══════════════════════════════════════════════════════════════════
 */

export interface ParkFormData {
  name: string;
  slug: string;
  description?: string;
  park_type: string;
  status: string;
  opening_date?: string;
  closing_date?: string;
  website_url?: string;
  phone?: string;
  email?: string;
  operator_id?: string;
  property_owner_id?: string;
  
  // Location can be stored as object for new submissions or ID for editing
  location?: {
    name: string;
    city?: string;
    state_province?: string;
    country: string;
    postal_code?: string;
    latitude: number;
    longitude: number;
    timezone?: string;
    display_name: string;
  };
  location_id?: string;
  
  images?: ImageAssignments;
  banner_image_url?: string;
  banner_image_id?: string;
  card_image_url?: string;
  card_image_id?: string;
}

export interface RideFormData {
  name: string;
  slug: string;
  description?: string;
  category: string;
  status: string;
  park_id: string;
  manufacturer_id?: string;
  designer_id?: string;
  ride_model_id?: string;
  opening_date?: string;
  closing_date?: string;
  max_speed_kmh?: number;
  max_height_meters?: number;
  length_meters?: number;
  duration_seconds?: number;
  capacity_per_hour?: number;
  height_requirement?: number;
  age_requirement?: number;
  inversions?: number;
  drop_height_meters?: number;
  max_g_force?: number;
  intensity_level?: string;
  coaster_type?: string;
  seating_type?: string;
  ride_sub_type?: string;
  images?: ImageAssignments;
  banner_image_url?: string;
  banner_image_id?: string;
  card_image_url?: string;
  card_image_id?: string;
}

export interface CompanyFormData {
  name: string;
  slug: string;
  description?: string;
  person_type: 'company' | 'individual' | 'firm' | 'organization';
  founded_year?: number;
  founded_date?: string;
  founded_date_precision?: string;
  headquarters_location?: string;
  website_url?: string;
  images?: ImageAssignments;
  banner_image_url?: string;
  banner_image_id?: string;
  card_image_url?: string;
  card_image_id?: string;
}

export interface RideModelFormData {
  name: string;
  slug: string;
  manufacturer_id: string;
  category: string;
  ride_type?: string;
  description?: string;
  images?: ImageAssignments;
  banner_image_url?: string;
  banner_image_id?: string;
  card_image_url?: string;
  card_image_id?: string;
}

/**
 * ═══════════════════════════════════════════════════════════════════
 * COMPOSITE SUBMISSION HANDLER
 * ═══════════════════════════════════════════════════════════════════
 * 
 * Creates a single submission containing multiple related entities
 * (e.g., Park + Operator, Ride + Manufacturer + Model)
 * 
 * All entities are submitted atomically through the moderation queue,
 * with dependency tracking to ensure correct approval order.
 * 
 * @param primaryEntity - The main entity being created (park or ride)
 * @param dependencies - Array of dependent entities (companies, models)
 * @param userId - The ID of the user submitting
 * @returns Object containing submitted boolean and submissionId
 */
async function submitCompositeCreation(
  primaryEntity: { type: 'park' | 'ride'; data: any },
  dependencies: CompositeSubmissionDependency[],
  userId: string
): Promise<{ submitted: boolean; submissionId: string }> {
  // Check if user is banned
  const { data: profile } = await supabase
    .from('profiles')
    .select('banned')
    .eq('user_id', userId)
    .single();

  if (profile?.banned) {
    throw new Error('Account suspended. Contact support for assistance.');
  }

  // Upload all pending images for all entities
  const uploadedEntities = await Promise.all([
    ...dependencies.map(async (dep) => {
      if (dep.data.images?.uploaded && dep.data.images.uploaded.length > 0) {
        const uploadedImages = await uploadPendingImages(dep.data.images.uploaded);
        return {
          ...dep,
          data: {
            ...dep.data,
            images: { ...dep.data.images, uploaded: uploadedImages }
          }
        };
      }
      return dep;
    }),
    (async () => {
      if (primaryEntity.data.images?.uploaded && primaryEntity.data.images.uploaded.length > 0) {
        const uploadedImages = await uploadPendingImages(primaryEntity.data.images.uploaded);
        return {
          ...primaryEntity,
          data: {
            ...primaryEntity.data,
            images: { ...primaryEntity.data.images, uploaded: uploadedImages }
          }
        };
      }
      return primaryEntity;
    })()
  ]);

  const uploadedDependencies = uploadedEntities.slice(0, -1) as CompositeSubmissionDependency[];
  const uploadedPrimary = uploadedEntities[uploadedEntities.length - 1] as typeof primaryEntity;

  // Build submission items array with dependencies first
  const submissionItems: any[] = [];
  const tempIdMap = new Map<string, number>(); // Maps tempId to order_index

  // Add dependency items (companies, models) first
  let orderIndex = 0;
  for (const dep of uploadedDependencies) {
    const itemType = dep.type === 'company' ? dep.companyType : dep.type;
    tempIdMap.set(dep.tempId, orderIndex);
    
    const itemData: any = {
      ...extractChangedFields(dep.data, {}),
      images: dep.data.images as unknown as Json
    };
    
    // Add company_type for company entities
    if (dep.type === 'company') {
      itemData.company_type = dep.companyType;
    }

    // Add manufacturer dependency for ride models
    if (dep.type === 'ride_model' && dep.parentTempId) {
      const parentOrderIndex = tempIdMap.get(dep.parentTempId);
      if (parentOrderIndex !== undefined) {
        itemData._temp_manufacturer_ref = parentOrderIndex;
      }
    }

    submissionItems.push({
      item_type: itemType,
      action_type: 'create' as const,
      item_data: itemData,
      status: 'pending' as const,
      order_index: orderIndex,
      depends_on: null // Dependencies don't have parents
    });

    orderIndex++;
  }

  // Add primary entity last
  const primaryData: any = {
    ...extractChangedFields(uploadedPrimary.data, {}),
    images: uploadedPrimary.data.images as unknown as Json
  };

  // Map temporary IDs to order indices for foreign keys
  if (uploadedPrimary.type === 'park') {
    if (uploadedPrimary.data.operator_id?.startsWith('temp-')) {
      const opIndex = tempIdMap.get('temp-operator');
      if (opIndex !== undefined) primaryData._temp_operator_ref = opIndex;
      delete primaryData.operator_id;
    }
    if (uploadedPrimary.data.property_owner_id?.startsWith('temp-')) {
      const ownerIndex = tempIdMap.get('temp-property-owner');
      const operatorIndex = tempIdMap.get('temp-operator');
      
      if (ownerIndex !== undefined) {
        primaryData._temp_property_owner_ref = ownerIndex;
      } else if (operatorIndex !== undefined) {
        // Property owner references operator (operator is owner scenario)
        primaryData._temp_property_owner_ref = operatorIndex;
      }
      delete primaryData.property_owner_id;
    }
  } else if (uploadedPrimary.type === 'ride') {
    if (uploadedPrimary.data.park_id?.startsWith('temp-')) {
      const parkIndex = tempIdMap.get(uploadedPrimary.data.park_id);
      if (parkIndex !== undefined) primaryData._temp_park_ref = parkIndex;
      delete primaryData.park_id;
    }
    if (uploadedPrimary.data.manufacturer_id?.startsWith('temp-')) {
      const mfgIndex = tempIdMap.get(uploadedPrimary.data.manufacturer_id);
      if (mfgIndex !== undefined) primaryData._temp_manufacturer_ref = mfgIndex;
      delete primaryData.manufacturer_id;
    }
    if (uploadedPrimary.data.designer_id?.startsWith('temp-')) {
      const designerIndex = tempIdMap.get(uploadedPrimary.data.designer_id);
      if (designerIndex !== undefined) primaryData._temp_designer_ref = designerIndex;
      delete primaryData.designer_id;
    }
    if (uploadedPrimary.data.ride_model_id?.startsWith('temp-')) {
      const modelIndex = tempIdMap.get(uploadedPrimary.data.ride_model_id);
      if (modelIndex !== undefined) primaryData._temp_ride_model_ref = modelIndex;
      delete primaryData.ride_model_id;
    }
  }

  submissionItems.push({
    item_type: uploadedPrimary.type,
    action_type: 'create' as const,
    item_data: primaryData,
    status: 'pending' as const,
    order_index: orderIndex,
    depends_on: null // Will be set by RPC based on refs
  });

  // Use RPC to create submission with items atomically
  const { data: result, error } = await supabase.rpc('create_submission_with_items', {
    p_user_id: userId,
    p_submission_type: uploadedPrimary.type,
    p_content: { action: 'create' } as unknown as Json,
    p_items: submissionItems as unknown as Json[]
  });

  if (error) {
    logger.error('Composite submission failed', {
      action: 'composite_submission',
      primaryType: uploadedPrimary.type,
      dependencyCount: dependencies.length,
      error: getErrorMessage(error)
    });
    throw new Error(`Failed to create composite submission: ${getErrorMessage(error)}`);
  }

  return { submitted: true, submissionId: result };
}

/**
 * ⚠️ CRITICAL SECURITY PATTERN ⚠️
 * 
 * Submits a new park for creation through the moderation queue.
 * This is the ONLY correct way to create parks.
 * 
 * DO NOT use direct database inserts:
 * ❌ await supabase.from('parks').insert(data)  // BYPASSES MODERATION!
 * ✅ await submitParkCreation(data, userId)      // CORRECT
 * 
 * Flow: User Submit → Moderation Queue → Approval → Versioning → Live
 * 
 * Even moderators/admins must use this function to ensure proper versioning and audit trails.
 * 
 * @see docs/SUBMISSION_FLOW.md for complete documentation
 * @param data - The park form data to submit
 * @param userId - The ID of the user submitting the park
 * @returns Object containing submitted boolean and submissionId
 */
export async function submitParkCreation(
  data: ParkFormData & { _compositeSubmission?: any },
  userId: string
): Promise<{ submitted: boolean; submissionId: string }> {
  // Check for composite submission with dependencies
  if (data._compositeSubmission) {
    const dependencies: CompositeSubmissionDependency[] = [];
    
    // Check if operator and owner are the same new entity
    const operatorIsOwner = 
      data._compositeSubmission.new_operator && 
      data._compositeSubmission.new_property_owner &&
      data._compositeSubmission.new_operator === data._compositeSubmission.new_property_owner;
    
    if (data._compositeSubmission.new_operator) {
      dependencies.push({
        type: 'company',
        data: { ...data._compositeSubmission.new_operator, company_type: 'operator' },
        tempId: 'temp-operator',
        companyType: 'operator'
      });
    }
    
    // Only add separate property owner if different from operator
    if (data._compositeSubmission.new_property_owner && !operatorIsOwner) {
      dependencies.push({
        type: 'company',
        data: { ...data._compositeSubmission.new_property_owner, company_type: 'property_owner' },
        tempId: 'temp-property-owner',
        companyType: 'property_owner'
      });
    }
    
    if (dependencies.length > 0) {
      return submitCompositeCreation(
        { type: 'park', data: data._compositeSubmission.park },
        dependencies,
        userId
      );
    }
  }

  // Standard single-entity creation
  // Check if user is banned
  const { data: profile } = await supabase
    .from('profiles')
    .select('banned')
    .eq('user_id', userId)
    .single();

  if (profile?.banned) {
    throw new Error('Account suspended. Contact support for assistance.');
  }

  // Upload any pending local images first
  let processedImages = data.images;
  if (data.images?.uploaded && data.images.uploaded.length > 0) {
    try {
      const uploadedImages = await uploadPendingImages(data.images.uploaded);
      processedImages = {
        ...data.images,
        uploaded: uploadedImages
      };
    } catch (error: unknown) {
      const errorMessage = getErrorMessage(error);
      logger.error('Park image upload failed', {
        action: 'park_creation',
        error: errorMessage
      });
      throw new Error(`Failed to upload images: ${errorMessage}`);
    }
  }

  // Create the main submission record
  const { data: submissionData, error: submissionError } = await supabase
    .from('content_submissions')
    .insert({
      user_id: userId,
      submission_type: 'park',
      content: {
        action: 'create'
      },
      status: 'pending' as const
    })
    .select('id')
    .single();

  if (submissionError) throw submissionError;

  // Extract images for assignment
  const changedFields = extractChangedFields(data, {});
  
  // Insert into relational park_submissions table
  const { data: parkSubmission, error: parkSubmissionError } = await supabase
    .from('park_submissions' as any)
    .insert({
      submission_id: submissionData.id,
      name: data.name,
      slug: data.slug,
      description: data.description || null,
      park_type: data.park_type,
      status: data.status,
      opening_date: data.opening_date ? new Date(data.opening_date).toISOString().split('T')[0] : null,
      closing_date: data.closing_date ? new Date(data.closing_date).toISOString().split('T')[0] : null,
      website_url: data.website_url || null,
      phone: data.phone || null,
      email: data.email || null,
      operator_id: data.operator_id || null,
      property_owner_id: data.property_owner_id || null,
      location_id: data.location_id || null,
      banner_image_url: changedFields.banner_image_url as string || null,
      banner_image_id: changedFields.banner_image_id as string || null,
      card_image_url: changedFields.card_image_url as string || null,
      card_image_id: changedFields.card_image_id as string || null
    } as any)
    .select('id')
    .single();

  if (parkSubmissionError) throw parkSubmissionError;

  // Create submission_items record linking to park_submissions
  const { error: itemError } = await supabase
    .from('submission_items')
    .insert({
      submission_id: submissionData.id,
      item_type: 'park',
      action_type: 'create',
      item_data_id: (parkSubmission as any).id,
      status: 'pending' as const,
      order_index: 0
    } as any);

  if (itemError) throw itemError;

  return { submitted: true, submissionId: submissionData.id };
}

/**
 * ⚠️ CRITICAL SECURITY PATTERN ⚠️
 * 
 * Submits an update to an existing park through the moderation queue.
 * This is the ONLY correct way to update parks.
 * 
 * DO NOT use direct database updates:
 * ❌ await supabase.from('parks').update(data)  // BYPASSES MODERATION!
 * ✅ await submitParkUpdate(parkId, data, userId) // CORRECT
 * 
 * Flow: User Submit → Moderation Queue → Approval → Versioning → Live
 * 
 * Even moderators/admins must use this function to ensure proper versioning and audit trails.
 * 
 * @see docs/SUBMISSION_FLOW.md for complete documentation
 * @param parkId - The ID of the park to update
 * @param data - The updated park form data
 * @param userId - The ID of the user submitting the update
 * @returns Object containing submitted boolean and submissionId
 */
export async function submitParkUpdate(
  parkId: string,
  data: ParkFormData,
  userId: string
): Promise<{ submitted: boolean; submissionId: string }> {
  // Check if user is banned
  const { data: profile } = await supabase
    .from('profiles')
    .select('banned')
    .eq('user_id', userId)
    .single();

  if (profile?.banned) {
    throw new Error('Account suspended. Contact support for assistance.');
  }

  // Fetch existing park data first
  const { data: existingPark, error: fetchError } = await supabase
    .from('parks')
    .select('id, name, slug, description, park_type, status, opening_date, opening_date_precision, closing_date, closing_date_precision, website_url, phone, email, location_id, operator_id, property_owner_id, banner_image_url, banner_image_id, card_image_url, card_image_id')
    .eq('id', parkId)
    .single();

  if (fetchError) throw new Error(`Failed to fetch park: ${fetchError.message}`);
  if (!existingPark) throw new Error('Park not found');

  // CRITICAL: Block new photo uploads on edits
  // Photos can only be submitted during creation or via the photo gallery
  if (data.images?.uploaded && data.images.uploaded.some(img => img.isLocal)) {
    throw new Error('Photo uploads are not allowed during edits. Please use the photo gallery to submit additional photos.');
  }

  // Only allow banner/card reassignments from existing photos
  let processedImages = data.images;

  // Create the main submission record
  const { data: submissionData, error: submissionError } = await supabase
    .from('content_submissions')
    .insert({
      user_id: userId,
      submission_type: 'park',
      content: {
        action: 'edit',
        park_id: parkId
      },
      status: 'pending' as const
    })
    .select('id')
    .single();

  if (submissionError) throw submissionError;

  // Create the submission item with actual park data AND original data
  const { error: itemError } = await supabase
    .from('submission_items')
    .insert({
      submission_id: submissionData.id,
      item_type: 'park',
      action_type: 'edit',
      item_data: JSON.parse(JSON.stringify({
        ...extractChangedFields(data, existingPark as any),
        park_id: parkId,  // Always include for relational integrity
        images: processedImages
      })) as Json,
      original_data: JSON.parse(JSON.stringify(existingPark)),
      status: 'pending' as const,
      order_index: 0
    });

  if (itemError) throw itemError;

  return { submitted: true, submissionId: submissionData.id };
}

/**
 * ⚠️ CRITICAL SECURITY PATTERN ⚠️
 * 
 * Submits a new ride for creation through the moderation queue.
 * This is the ONLY correct way to create rides.
 * 
 * DO NOT use direct database inserts:
 * ❌ await supabase.from('rides').insert(data)  // BYPASSES MODERATION!
 * ✅ await submitRideCreation(data, userId)      // CORRECT
 * 
 * Flow: User Submit → Moderation Queue → Approval → Versioning → Live
 * 
 * Even moderators/admins must use this function to ensure proper versioning and audit trails.
 * 
 * @see docs/SUBMISSION_FLOW.md for complete documentation
 * @param data - The ride form data to submit
 * @param userId - The ID of the user submitting the ride
 * @returns Object containing submitted boolean and submissionId
 */
export async function submitRideCreation(
  data: RideFormData & { 
    _tempNewPark?: any;
    _tempNewManufacturer?: any; 
    _tempNewDesigner?: any;
    _tempNewRideModel?: any;
  },
  userId: string
): Promise<{ submitted: boolean; submissionId: string }> {
  // Check for composite submission with dependencies
  if (data._tempNewPark || data._tempNewManufacturer || data._tempNewDesigner || data._tempNewRideModel) {
    const dependencies: CompositeSubmissionDependency[] = [];
    
    // Handle new park operator (from nested park)
    if (data._tempNewPark?._tempNewOperator) {
      dependencies.push({
        type: 'company',
        data: { ...data._tempNewPark._tempNewOperator, company_type: 'operator' },
        tempId: 'temp-park-operator',
        companyType: 'operator'
      });
    }
    
    // Handle new park property owner (from nested park)
    if (data._tempNewPark?._tempNewPropertyOwner) {
      dependencies.push({
        type: 'company',
        data: { ...data._tempNewPark._tempNewPropertyOwner, company_type: 'property_owner' },
        tempId: 'temp-park-owner',
        companyType: 'property_owner'
      });
    }
    
    // Handle new park (depends on operator/owner)
    if (data._tempNewPark) {
      dependencies.push({
        type: 'park',
        data: {
          ...data._tempNewPark,
          operator_id: data._tempNewPark._tempNewOperator ? 'temp-park-operator' : data._tempNewPark.operator_id,
          property_owner_id: data._tempNewPark._tempNewPropertyOwner ? 'temp-park-owner' : data._tempNewPark.property_owner_id,
          _tempNewOperator: undefined,
          _tempNewPropertyOwner: undefined
        },
        tempId: 'temp-park'
      });
    }
    
    // Handle new manufacturer
    if (data._tempNewManufacturer) {
      dependencies.push({
        type: 'company',
        data: { ...data._tempNewManufacturer, company_type: 'manufacturer' },
        tempId: 'temp-manufacturer',
        companyType: 'manufacturer'
      });
    }
    
    // Handle new designer
    if (data._tempNewDesigner) {
      dependencies.push({
        type: 'company',
        data: { ...data._tempNewDesigner, company_type: 'designer' },
        tempId: 'temp-designer',
        companyType: 'designer'
      });
    }
    
    // Handle new ride model (depends on manufacturer)
    if (data._tempNewRideModel) {
      dependencies.push({
        type: 'ride_model',
        data: {
          ...data._tempNewRideModel,
          manufacturer_id: data._tempNewManufacturer ? 'temp-manufacturer' : data._tempNewRideModel.manufacturer_id
        },
        tempId: 'temp-ride-model',
        parentTempId: data._tempNewManufacturer ? 'temp-manufacturer' : undefined
      });
    }
    
    if (dependencies.length > 0) {
      // Prepare ride data with temp references
      const rideData = {
        ...data,
        park_id: data._tempNewPark ? 'temp-park' : data.park_id,
        manufacturer_id: data._tempNewManufacturer ? 'temp-manufacturer' : data.manufacturer_id,
        designer_id: data._tempNewDesigner ? 'temp-designer' : data.designer_id,
        ride_model_id: data._tempNewRideModel ? 'temp-ride-model' : data.ride_model_id,
        _tempNewPark: undefined,
        _tempNewManufacturer: undefined,
        _tempNewDesigner: undefined,
        _tempNewRideModel: undefined
      };
      
      return submitCompositeCreation(
        { type: 'ride', data: rideData },
        dependencies,
        userId
      );
    }
  }

  // Standard single-entity creation
  // Check if user is banned
  const { data: profile } = await supabase
    .from('profiles')
    .select('banned')
    .eq('user_id', userId)
    .single();

  if (profile?.banned) {
    throw new Error('Account suspended. Contact support for assistance.');
  }

  // Upload any pending local images first
  let processedImages = data.images;
  if (data.images?.uploaded && data.images.uploaded.length > 0) {
    try {
      const uploadedImages = await uploadPendingImages(data.images.uploaded);
      processedImages = {
        ...data.images,
        uploaded: uploadedImages
      };
    } catch (error: unknown) {
      const errorMessage = getErrorMessage(error);
      logger.error('Ride image upload failed', {
        action: 'ride_creation',
        error: errorMessage
      });
      throw new Error(`Failed to upload images: ${errorMessage}`);
    }
  }

  // Create the main submission record
  const { data: submissionData, error: submissionError } = await supabase
    .from('content_submissions')
    .insert({
      user_id: userId,
      submission_type: 'ride',
      content: {
        action: 'create'
      },
      status: 'pending' as const
    })
    .select('id')
    .single();

  if (submissionError) throw submissionError;

  // Extract images for assignment
  const changedFields = extractChangedFields(data, {});

  // Insert into relational ride_submissions table
  const { data: rideSubmission, error: rideSubmissionError } = await supabase
    .from('ride_submissions' as any)
    .insert({
      submission_id: submissionData.id,
      park_id: data.park_id || null,
      name: data.name,
      slug: data.slug,
      description: data.description || null,
      category: data.category,
      ride_sub_type: data.ride_sub_type || null,
      status: data.status,
      opening_date: data.opening_date ? new Date(data.opening_date).toISOString().split('T')[0] : null,
      closing_date: data.closing_date ? new Date(data.closing_date).toISOString().split('T')[0] : null,
      manufacturer_id: data.manufacturer_id || null,
      designer_id: data.designer_id || null,
      ride_model_id: data.ride_model_id || null,
      height_requirement: data.height_requirement || null,
      age_requirement: data.age_requirement || null,
      capacity_per_hour: data.capacity_per_hour || null,
      duration_seconds: data.duration_seconds || null,
      max_speed_kmh: data.max_speed_kmh || null,
      max_height_meters: data.max_height_meters || null,
      length_meters: data.length_meters || null,
      drop_height_meters: data.drop_height_meters || null,
      inversions: data.inversions || 0,
      max_g_force: data.max_g_force || null,
      coaster_type: data.coaster_type || null,
      seating_type: data.seating_type || null,
      intensity_level: data.intensity_level || null,
      banner_image_url: changedFields.banner_image_url as string || null,
      banner_image_id: changedFields.banner_image_id as string || null,
      card_image_url: changedFields.card_image_url as string || null,
      card_image_id: changedFields.card_image_id as string || null,
      image_url: null
    } as any)
    .select('id')
    .single();

  if (rideSubmissionError) throw rideSubmissionError;

  // Create submission_items record linking to ride_submissions
  const { error: itemError } = await supabase
    .from('submission_items')
    .insert({
      submission_id: submissionData.id,
      item_type: 'ride',
      action_type: 'create',
      item_data_id: (rideSubmission as any).id,
      status: 'pending' as const,
      order_index: 0
    } as any);

  if (itemError) throw itemError;

  return { submitted: true, submissionId: submissionData.id };
}

/**
 * ⚠️ CRITICAL SECURITY PATTERN ⚠️
 * 
 * Submits an update to an existing ride through the moderation queue.
 * This is the ONLY correct way to update rides.
 * 
 * DO NOT use direct database updates:
 * ❌ await supabase.from('rides').update(data)  // BYPASSES MODERATION!
 * ✅ await submitRideUpdate(rideId, data, userId) // CORRECT
 * 
 * Flow: User Submit → Moderation Queue → Approval → Versioning → Live
 * 
 * Even moderators/admins must use this function to ensure proper versioning and audit trails.
 * 
 * @see docs/SUBMISSION_FLOW.md for complete documentation
 * @param rideId - The ID of the ride to update
 * @param data - The updated ride form data
 * @param userId - The ID of the user submitting the update
 * @returns Object containing submitted boolean and submissionId
 */
export async function submitRideUpdate(
  rideId: string,
  data: RideFormData,
  userId: string
): Promise<{ submitted: boolean; submissionId: string }> {
  // Check if user is banned
  const { data: profile } = await supabase
    .from('profiles')
    .select('banned')
    .eq('user_id', userId)
    .single();

  if (profile?.banned) {
    throw new Error('Account suspended. Contact support for assistance.');
  }

  // Fetch existing ride data first
  const { data: existingRide, error: fetchError } = await supabase
    .from('rides')
    .select('*')
    .eq('id', rideId)
    .single();

  if (fetchError) throw new Error(`Failed to fetch ride: ${fetchError.message}`);
  if (!existingRide) throw new Error('Ride not found');

  // CRITICAL: Block new photo uploads on edits
  // Photos can only be submitted during creation or via the photo gallery
  if (data.images?.uploaded && data.images.uploaded.some(img => img.isLocal)) {
    throw new Error('Photo uploads are not allowed during edits. Please use the photo gallery to submit additional photos.');
  }

  // Only allow banner/card reassignments from existing photos
  let processedImages = data.images;

  // Create the main submission record
  const { data: submissionData, error: submissionError } = await supabase
    .from('content_submissions')
    .insert({
      user_id: userId,
      submission_type: 'ride',
      content: {
        action: 'edit',
        ride_id: rideId
      },
      status: 'pending' as const
    })
    .select()
    .single();

  if (submissionError) throw submissionError;

  // Create the submission item with actual ride data AND original data
  const { error: itemError } = await supabase
    .from('submission_items')
    .insert({
      submission_id: submissionData.id,
      item_type: 'ride',
      action_type: 'edit',
      item_data: {
        ...extractChangedFields(data, existingRide as any),
        ride_id: rideId,  // Always include for relational integrity
        images: processedImages as unknown as Json
      },
      original_data: JSON.parse(JSON.stringify(existingRide)),
      status: 'pending' as const,
      order_index: 0
    });

  if (itemError) throw itemError;

  return { submitted: true, submissionId: submissionData.id };
}

/**
 * ⚠️ CRITICAL SECURITY PATTERN ⚠️
 * 
 * Submits a new ride model for creation through the moderation queue.
 * This is the ONLY correct way to create ride models.
 * 
 * DO NOT use direct database inserts:
 * ❌ await supabase.from('ride_models').insert(data)  // BYPASSES MODERATION!
 * ✅ await submitRideModelCreation(data, userId)      // CORRECT
 * 
 * Flow: User Submit → Moderation Queue → Approval → Versioning → Live
 * 
 * @param data - The ride model form data to submit
 * @param userId - The ID of the user submitting the ride model
 * @returns Object containing submitted boolean and submissionId
 */
export async function submitRideModelCreation(
  data: RideModelFormData,
  userId: string
): Promise<{ submitted: boolean; submissionId: string }> {
  // Check if user is banned
  const { data: profile } = await supabase
    .from('profiles')
    .select('banned')
    .eq('user_id', userId)
    .single();

  if (profile?.banned) {
    throw new Error('Account suspended. Contact support for assistance.');
  }

  // Upload any pending local images first
  let processedImages = data.images;
  if (data.images?.uploaded && data.images.uploaded.length > 0) {
    try {
      const uploadedImages = await uploadPendingImages(data.images.uploaded);
      processedImages = {
        ...data.images,
        uploaded: uploadedImages
      };
    } catch (error: unknown) {
      const errorMessage = getErrorMessage(error);
      logger.error('Ride model image upload failed', {
        action: 'ride_model_creation',
        error: errorMessage
      });
      throw new Error(`Failed to upload images: ${errorMessage}`);
    }
  }

  // Create the main submission record
  const { data: submissionData, error: submissionError } = await supabase
    .from('content_submissions')
    .insert({
      user_id: userId,
      submission_type: 'ride_model',
      content: {
        action: 'create'
      },
      status: 'pending' as const
    })
    .select()
    .single();

  if (submissionError) throw submissionError;

  // Create the submission item with actual ride model data
  const { error: itemError } = await supabase
    .from('submission_items')
    .insert({
      submission_id: submissionData.id,
      item_type: 'ride_model',
      action_type: 'create',
      item_data: {
        ...extractChangedFields(data, {}),
        images: processedImages as unknown as Json
      },
      status: 'pending' as const,
      order_index: 0
    });

  if (itemError) throw itemError;

  return { submitted: true, submissionId: submissionData.id };
}

/**
 * ⚠️ CRITICAL SECURITY PATTERN ⚠️
 * 
 * Submits a ride model update through the moderation queue.
 * This is the ONLY correct way to update ride models.
 */
export async function submitRideModelUpdate(
  rideModelId: string,
  data: RideModelFormData,
  userId: string
): Promise<{ submitted: boolean; submissionId: string }> {
  // Check if user is banned
  const { data: profile } = await supabase
    .from('profiles')
    .select('banned')
    .eq('user_id', userId)
    .single();

  if (profile?.banned) {
    throw new Error('Account suspended. Contact support for assistance.');
  }

  // Fetch existing ride model
  const { data: existingModel, error: fetchError } = await supabase
    .from('ride_models')
    .select('*')
    .eq('id', rideModelId)
    .single();

  if (fetchError) throw new Error(`Failed to fetch ride model: ${fetchError.message}`);
  if (!existingModel) throw new Error('Ride model not found');

  // CRITICAL: Block new photo uploads on edits
  if (data.images?.uploaded && data.images.uploaded.some(img => img.isLocal)) {
    throw new Error('Photo uploads are not allowed during edits. Please use the photo gallery to submit additional photos.');
  }

  let processedImages = data.images;

  // Create the main submission record
  const { data: submissionData, error: submissionError } = await supabase
    .from('content_submissions')
    .insert({
      user_id: userId,
      submission_type: 'ride_model',
      content: {
        action: 'edit',
        ride_model_id: rideModelId
      },
      status: 'pending' as const
    })
    .select()
    .single();

  if (submissionError) throw submissionError;

  // Create the submission item with actual ride model data
  const { error: itemError } = await supabase
    .from('submission_items')
    .insert({
      submission_id: submissionData.id,
      item_type: 'ride_model',
      action_type: 'edit',
      item_data: {
        ...extractChangedFields(data, existingModel as any),
        ride_model_id: rideModelId,  // Always include for relational integrity
        images: processedImages as unknown as Json
      },
      original_data: JSON.parse(JSON.stringify(existingModel)),
      status: 'pending' as const,
      order_index: 0
    });

  if (itemError) throw itemError;

  return { submitted: true, submissionId: submissionData.id };
}

/**
 * ⚠️ CRITICAL SECURITY PATTERN ⚠️
 * 
 * Submits a new manufacturer for creation through the moderation queue.
 */
export async function submitManufacturerCreation(
  data: CompanyFormData,
  userId: string
): Promise<{ submitted: boolean; submissionId: string }> {
  let processedImages = data.images;
  if (data.images?.uploaded && data.images.uploaded.length > 0) {
    try {
      const uploadedImages = await uploadPendingImages(data.images.uploaded);
      processedImages = { ...data.images, uploaded: uploadedImages };
    } catch (error: unknown) {
      const errorMessage = getErrorMessage(error);
      logger.error('Company image upload failed', {
        action: 'manufacturer_creation',
        error: errorMessage
      });
      throw new Error(`Failed to upload images: ${errorMessage}`);
    }
  }

  const { data: submissionData, error: submissionError } = await supabase
    .from('content_submissions')
    .insert({
      user_id: userId,
      submission_type: 'manufacturer',
      content: { action: 'create' },
      status: 'pending' as const
    })
    .select()
    .single();

  if (submissionError) throw submissionError;

  const { error: itemError } = await supabase
    .from('submission_items')
    .insert({
      submission_id: submissionData.id,
      item_type: 'manufacturer',
      action_type: 'create',
      item_data: {
        ...extractChangedFields(data, {}),
        company_type: 'manufacturer',
        images: processedImages as unknown as Json
      },
      status: 'pending' as const,
      order_index: 0
    });

  if (itemError) throw itemError;

  return { submitted: true, submissionId: submissionData.id };
}

export async function submitManufacturerUpdate(
  companyId: string,
  data: CompanyFormData,
  userId: string
): Promise<{ submitted: boolean; submissionId: string }> {
  const { data: existingCompany, error: fetchError } = await supabase
    .from('companies')
    .select('*')
    .eq('id', companyId)
    .single();

  if (fetchError) throw new Error(`Failed to fetch manufacturer: ${fetchError.message}`);
  if (!existingCompany) throw new Error('Manufacturer not found');

  // CRITICAL: Block new photo uploads on edits
  if (data.images?.uploaded && data.images.uploaded.some(img => img.isLocal)) {
    throw new Error('Photo uploads are not allowed during edits. Please use the photo gallery to submit additional photos.');
  }

  let processedImages = data.images;

  const { data: submissionData, error: submissionError } = await supabase
    .from('content_submissions')
    .insert({
      user_id: userId,
      submission_type: 'manufacturer',
      content: { action: 'edit', company_id: companyId },
      status: 'pending' as const
    })
    .select()
    .single();

  if (submissionError) throw submissionError;

  const { error: itemError } = await supabase
    .from('submission_items')
    .insert({
      submission_id: submissionData.id,
      item_type: 'manufacturer',
      action_type: 'edit',
      item_data: {
        ...extractChangedFields(data, existingCompany as any),
        company_id: companyId,  // Always include for relational integrity
        company_type: 'manufacturer',  // Always include for entity type discrimination
        images: processedImages as unknown as Json
      },
      original_data: JSON.parse(JSON.stringify(existingCompany)),
      status: 'pending' as const,
      order_index: 0
    });

  if (itemError) throw itemError;

  return { submitted: true, submissionId: submissionData.id };
}

export async function submitDesignerCreation(
  data: CompanyFormData,
  userId: string
): Promise<{ submitted: boolean; submissionId: string }> {
  let processedImages = data.images;
  if (data.images?.uploaded && data.images.uploaded.length > 0) {
    try {
      const uploadedImages = await uploadPendingImages(data.images.uploaded);
      processedImages = { ...data.images, uploaded: uploadedImages };
    } catch (error: unknown) {
      const errorMessage = getErrorMessage(error);
      logger.error('Company image upload failed', {
        action: 'designer_creation',
        error: errorMessage
      });
      throw new Error(`Failed to upload images: ${errorMessage}`);
    }
  }

  const { data: submissionData, error: submissionError } = await supabase
    .from('content_submissions')
    .insert({
      user_id: userId,
      submission_type: 'designer',
      content: { action: 'create' },
      status: 'pending' as const
    })
    .select()
    .single();

  if (submissionError) throw submissionError;

  const { error: itemError } = await supabase
    .from('submission_items')
    .insert({
      submission_id: submissionData.id,
      item_type: 'designer',
      action_type: 'create',
      item_data: {
        ...extractChangedFields(data, {}),
        company_type: 'designer',
        images: processedImages as unknown as Json
      },
      status: 'pending' as const,
      order_index: 0
    });

  if (itemError) throw itemError;

  return { submitted: true, submissionId: submissionData.id };
}

export async function submitDesignerUpdate(
  companyId: string,
  data: CompanyFormData,
  userId: string
): Promise<{ submitted: boolean; submissionId: string }> {
  const { data: existingCompany, error: fetchError } = await supabase
    .from('companies')
    .select('*')
    .eq('id', companyId)
    .single();

  if (fetchError) throw new Error(`Failed to fetch designer: ${fetchError.message}`);
  if (!existingCompany) throw new Error('Designer not found');

  // CRITICAL: Block new photo uploads on edits
  if (data.images?.uploaded && data.images.uploaded.some(img => img.isLocal)) {
    throw new Error('Photo uploads are not allowed during edits. Please use the photo gallery to submit additional photos.');
  }

  let processedImages = data.images;

  const { data: submissionData, error: submissionError } = await supabase
    .from('content_submissions')
    .insert({
      user_id: userId,
      submission_type: 'designer',
      content: { action: 'edit', company_id: companyId },
      status: 'pending' as const
    })
    .select()
    .single();

  if (submissionError) throw submissionError;

  const { error: itemError } = await supabase
    .from('submission_items')
    .insert({
      submission_id: submissionData.id,
      item_type: 'designer',
      action_type: 'edit',
      item_data: {
        ...extractChangedFields(data, existingCompany as any),
        company_id: companyId,  // Always include for relational integrity
        company_type: 'designer',  // Always include for entity type discrimination
        images: processedImages as unknown as Json
      },
      original_data: JSON.parse(JSON.stringify(existingCompany)),
      status: 'pending' as const,
      order_index: 0
    });

  if (itemError) throw itemError;

  return { submitted: true, submissionId: submissionData.id };
}

export async function submitOperatorCreation(
  data: CompanyFormData,
  userId: string
): Promise<{ submitted: boolean; submissionId: string }> {
  let processedImages = data.images;
  if (data.images?.uploaded && data.images.uploaded.length > 0) {
    try {
      const uploadedImages = await uploadPendingImages(data.images.uploaded);
      processedImages = { ...data.images, uploaded: uploadedImages };
    } catch (error: unknown) {
      const errorMessage = getErrorMessage(error);
      logger.error('Company image upload failed', {
        action: 'operator_creation',
        error: errorMessage
      });
      throw new Error(`Failed to upload images: ${errorMessage}`);
    }
  }

  const { data: submissionData, error: submissionError } = await supabase
    .from('content_submissions')
    .insert({
      user_id: userId,
      submission_type: 'operator',
      content: { action: 'create' },
      status: 'pending' as const
    })
    .select()
    .single();

  if (submissionError) throw submissionError;

  const { error: itemError } = await supabase
    .from('submission_items')
    .insert({
      submission_id: submissionData.id,
      item_type: 'operator',
      action_type: 'create',
      item_data: {
        ...extractChangedFields(data, {}),
        company_type: 'operator',
        images: processedImages as unknown as Json
      },
      status: 'pending' as const,
      order_index: 0
    });

  if (itemError) throw itemError;

  return { submitted: true, submissionId: submissionData.id };
}

export async function submitOperatorUpdate(
  companyId: string,
  data: CompanyFormData,
  userId: string
): Promise<{ submitted: boolean; submissionId: string }> {
  const { data: existingCompany, error: fetchError } = await supabase
    .from('companies')
    .select('*')
    .eq('id', companyId)
    .single();

  if (fetchError) throw new Error(`Failed to fetch operator: ${fetchError.message}`);
  if (!existingCompany) throw new Error('Operator not found');

  // CRITICAL: Block new photo uploads on edits
  if (data.images?.uploaded && data.images.uploaded.some(img => img.isLocal)) {
    throw new Error('Photo uploads are not allowed during edits. Please use the photo gallery to submit additional photos.');
  }

  let processedImages = data.images;

  const { data: submissionData, error: submissionError } = await supabase
    .from('content_submissions')
    .insert({
      user_id: userId,
      submission_type: 'operator',
      content: { action: 'edit', company_id: companyId },
      status: 'pending' as const
    })
    .select()
    .single();

  if (submissionError) throw submissionError;

  const { error: itemError } = await supabase
    .from('submission_items')
    .insert({
      submission_id: submissionData.id,
      item_type: 'operator',
      action_type: 'edit',
      item_data: {
        ...extractChangedFields(data, existingCompany as any),
        company_id: companyId,  // Always include for relational integrity
        company_type: 'operator',  // Always include for entity type discrimination
        images: processedImages as unknown as Json
      },
      original_data: JSON.parse(JSON.stringify(existingCompany)),
      status: 'pending' as const,
      order_index: 0
    });

  if (itemError) throw itemError;

  return { submitted: true, submissionId: submissionData.id };
}

export async function submitPropertyOwnerCreation(
  data: CompanyFormData,
  userId: string
): Promise<{ submitted: boolean; submissionId: string }> {
  let processedImages = data.images;
  if (data.images?.uploaded && data.images.uploaded.length > 0) {
    try {
      const uploadedImages = await uploadPendingImages(data.images.uploaded);
      processedImages = { ...data.images, uploaded: uploadedImages };
    } catch (error: unknown) {
      const errorMessage = getErrorMessage(error);
      logger.error('Company image upload failed', {
        action: 'property_owner_creation',
        error: errorMessage
      });
      throw new Error(`Failed to upload images: ${errorMessage}`);
    }
  }

  const { data: submissionData, error: submissionError } = await supabase
    .from('content_submissions')
    .insert({
      user_id: userId,
      submission_type: 'property_owner',
      content: { action: 'create' },
      status: 'pending' as const
    })
    .select()
    .single();

  if (submissionError) throw submissionError;

  const { error: itemError } = await supabase
    .from('submission_items')
    .insert({
      submission_id: submissionData.id,
      item_type: 'property_owner',
      action_type: 'create',
      item_data: {
        ...extractChangedFields(data, {}),
        company_type: 'property_owner',
        images: processedImages as unknown as Json
      },
      status: 'pending' as const,
      order_index: 0
    });

  if (itemError) throw itemError;

  return { submitted: true, submissionId: submissionData.id };
}

export async function submitPropertyOwnerUpdate(
  companyId: string,
  data: CompanyFormData,
  userId: string
): Promise<{ submitted: boolean; submissionId: string }> {
  const { data: existingCompany, error: fetchError } = await supabase
    .from('companies')
    .select('*')
    .eq('id', companyId)
    .single();

  if (fetchError) throw new Error(`Failed to fetch property owner: ${fetchError.message}`);
  if (!existingCompany) throw new Error('Property owner not found');

  // CRITICAL: Block new photo uploads on edits
  if (data.images?.uploaded && data.images.uploaded.some(img => img.isLocal)) {
    throw new Error('Photo uploads are not allowed during edits. Please use the photo gallery to submit additional photos.');
  }

  let processedImages = data.images;

  const { data: submissionData, error: submissionError } = await supabase
    .from('content_submissions')
    .insert({
      user_id: userId,
      submission_type: 'property_owner',
      content: { action: 'edit', company_id: companyId },
      status: 'pending' as const
    })
    .select()
    .single();

  if (submissionError) throw submissionError;

  const { error: itemError } = await supabase
    .from('submission_items')
    .insert({
      submission_id: submissionData.id,
      item_type: 'property_owner',
      action_type: 'edit',
      item_data: {
        ...extractChangedFields(data, existingCompany as any),
        company_id: companyId,  // Always include for relational integrity
        company_type: 'property_owner',  // Always include for entity type discrimination
        images: processedImages as unknown as Json
      },
      original_data: JSON.parse(JSON.stringify(existingCompany)),
      status: 'pending' as const,
      order_index: 0
    });

  if (itemError) throw itemError;

  return { submitted: true, submissionId: submissionData.id };
}

/**
 * ⚠️ CRITICAL SECURITY PATTERN ⚠️
 * 
 * Submits a new timeline event for an entity through the moderation queue.
 * 
 * DO NOT write directly to entity_timeline_events:
 * ❌ await supabase.from('entity_timeline_events').insert(data)  // BYPASSES MODERATION!
 * ✅ await submitTimelineEvent(entityType, entityId, data, userId)  // CORRECT
 * 
 * Flow: User Submit → Moderation Queue → Approval → Database Write
 * 
 * @param entityType - Type of entity (park, ride, company)
 * @param entityId - ID of the entity
 * @param data - The timeline event form data
 * @param userId - The ID of the user submitting
 * @returns Object containing submitted boolean and submissionId
 */
export async function submitTimelineEvent(
  entityType: EntityType,
  entityId: string,
  data: TimelineEventFormData,
  userId: string
): Promise<{ submitted: boolean; submissionId: string }> {
  // Validate user
  if (!userId) {
    throw new Error('User ID is required for timeline event submission');
  }

  // Create submission content (minimal reference data only)
  const content: Json = {
    action: 'create',
    entity_type: entityType,
    entity_id: entityId,
  };

  // Create the main submission record
  // Use atomic RPC function to create submission + items in transaction
  const itemData: Record<string, any> = {
    entity_type: entityType,
    entity_id: entityId,
    event_type: data.event_type,
    event_date: data.event_date.toISOString().split('T')[0],
    event_date_precision: data.event_date_precision,
    title: data.title,
    description: data.description,
    from_value: data.from_value,
    to_value: data.to_value,
    from_entity_id: data.from_entity_id,
    to_entity_id: data.to_entity_id,
    from_location_id: data.from_location_id,
    to_location_id: data.to_location_id,
    is_public: true,
  };

  const items = [{
    item_type: 'timeline_event',
    action_type: 'create',
    item_data: itemData,
    order_index: 0,
  }];

  const { data: submissionId, error } = await supabase
    .rpc('create_submission_with_items', {
      p_user_id: userId,
      p_submission_type: 'timeline_event',
      p_content: content,
      p_items: items as unknown as Json[],
    });

  if (error || !submissionId) {
    const errorMessage = getErrorMessage(error);
    logger.error('Timeline event submission failed', {
      action: 'create_timeline_event',
      userId,
      error: errorMessage
    });
    throw new Error('Failed to submit timeline event for review');
  }

  return {
    submitted: true,
    submissionId: submissionId,
  };
}

/**
 * ⚠️ CRITICAL SECURITY PATTERN ⚠️
 * 
 * Submits an update to an existing timeline event through the moderation queue.
 * 
 * @param eventId - ID of the existing timeline event
 * @param data - The updated timeline event data
 * @param userId - The ID of the user submitting the update
 * @returns Object containing submitted boolean and submissionId
 */
export async function submitTimelineEventUpdate(
  eventId: string,
  data: TimelineEventFormData,
  userId: string
): Promise<{ submitted: boolean; submissionId: string }> {
  // Fetch original event
  const { data: originalEvent, error: fetchError } = await supabase
    .from('entity_timeline_events')
    .select('*')
    .eq('id', eventId)
    .single();

  if (fetchError || !originalEvent) {
    throw new Error('Failed to fetch original timeline event');
  }

  // Extract only changed fields from form data
  const changedFields = extractChangedFields(data, originalEvent as Partial<Record<string, unknown>>);

  const itemData: Record<string, unknown> = {
    ...changedFields,
    // Always include entity reference (for FK integrity)
    entity_type: originalEvent.entity_type,
    entity_id: originalEvent.entity_id,
    is_public: true,
  };

  // Use atomic RPC function to create submission and item together
  const { data: result, error: rpcError } = await supabase.rpc(
    'create_submission_with_items',
    {
      p_user_id: userId,
      p_submission_type: 'timeline_event',
      p_content: {
        action: 'edit',
        event_id: eventId,
        entity_type: originalEvent.entity_type,
      } as unknown as Json,
      p_items: [
        {
          item_type: 'timeline_event',
          action_type: 'edit',
          item_data: itemData,
          original_data: originalEvent,
          status: 'pending' as const,
          order_index: 0,
        }
      ] as unknown as Json[],
    }
  );

  if (rpcError || !result) {
    const errorMessage = getErrorMessage(rpcError);
    logger.error('Timeline event update failed', {
      action: 'update_timeline_event',
      eventId,
      error: errorMessage
    });
    throw new Error('Failed to submit timeline event update');
  }

  return {
    submitted: true,
    submissionId: result,
  };
}


export async function deleteTimelineEvent(
  eventId: string,
  userId: string
): Promise<void> {
  // First verify the event exists and user has permission
  const { data: event, error: fetchError } = await supabase
    .from('entity_timeline_events')
    .select('created_by, approved_by')
    .eq('id', eventId)
    .single();

  if (fetchError) {
    const errorMessage = getErrorMessage(fetchError);
    logger.error('Timeline event fetch failed', {
      action: 'delete_timeline_event',
      eventId,
      error: errorMessage
    });
    throw new Error('Timeline event not found');
  }

  if (!event) {
    throw new Error('Timeline event not found');
  }

  // Only allow deletion of own unapproved events
  if (event.created_by !== userId) {
    throw new Error('You can only delete your own timeline events');
  }

  if (event.approved_by !== null) {
    throw new Error('Cannot delete approved timeline events');
  }

  // Delete the event
  const { error: deleteError } = await supabase
    .from('entity_timeline_events')
    .delete()
    .eq('id', eventId);

  if (deleteError) {
    const errorMessage = getErrorMessage(deleteError);
    logger.error('Timeline event deletion failed', {
      action: 'delete_timeline_event',
      eventId,
      error: errorMessage
    });
    throw new Error('Failed to delete timeline event');
  }

  logger.info('Timeline event deleted', {
    action: 'delete_timeline_event',
    eventId,
    userId
  });
}
