import type { SubmissionItemData } from '@/types/submissions';
import type { 
  ParkSubmissionData, 
  RideSubmissionData, 
  CompanySubmissionData,
  RideModelSubmissionData 
} from '@/types/submission-data';
import { supabase } from '@/integrations/supabase/client';
import { logger } from './logger';
import { getErrorMessage } from './errorHandler';

type SubmissionDataTypes = 
  | ParkSubmissionData 
  | RideSubmissionData 
  | CompanySubmissionData 
  | RideModelSubmissionData;

export interface FieldChange {
  field: string;
  oldValue: any;
  newValue: any;
  changeType: 'added' | 'removed' | 'modified';
  metadata?: {
    isCreatingNewLocation?: boolean;
    precision?: 'day' | 'month' | 'year';
    oldPrecision?: 'day' | 'month' | 'year';
    newPrecision?: 'day' | 'month' | 'year';
  };
}

export interface ImageChange {
  type: 'banner' | 'card';
  oldUrl?: string;
  newUrl?: string;
  oldId?: string;
  newId?: string;
}

export interface PhotoChange {
  type: 'added' | 'edited' | 'deleted';
  photos?: Array<{ url: string; title?: string; caption?: string }>;
  photo?: {
    url: string;
    title?: string;
    caption?: string;
    oldCaption?: string;
    newCaption?: string;
    oldTitle?: string;
    newTitle?: string;
    entity_type?: string;
    entity_name?: string;
    deletion_reason?: string;
  };
}

export interface ChangesSummary {
  action: 'create' | 'edit' | 'delete';
  entityType: string;
  entityName?: string;
  fieldChanges: FieldChange[];
  imageChanges: ImageChange[];
  photoChanges: PhotoChange[];
  hasLocationChange: boolean;
  totalChanges: number;
}

/**
 * Detects photo changes for a submission
 */
async function detectPhotoChanges(submissionId: string): Promise<PhotoChange[]> {
  const changes: PhotoChange[] = [];
  
  try {
    // First check for photo submission items (photo additions)
    const { data: photoSubmissions, error: photoError } = await supabase
      .from('photo_submissions')
      .select(`
        *,
        items:photo_submission_items(*)
      `)
      .eq('submission_id', submissionId);

    if (photoError) {
      const errorMessage = getErrorMessage(photoError);
      logger.error('Photo submission fetch failed', {
        action: 'detect_photo_changes',
        submissionId,
        error: errorMessage
      });
    } else {
      const photoSubmission = photoSubmissions?.[0];
      if (photoSubmission?.items && photoSubmission.items.length > 0) {
        changes.push({
          type: 'added',
          photos: photoSubmission.items.map((item: any) => ({
            url: item.cloudflare_image_url,
            title: item.title,
            caption: item.caption
          }))
        });
      }
    }

    // Check for photo edits and deletions in submission_items
    const { data: submissionItems, error: itemsError } = await supabase
      .from('submission_items')
      .select('*')
      .eq('submission_id', submissionId)
      .in('item_type', ['photo_edit', 'photo_delete']);

    if (itemsError) {
      const errorMessage = getErrorMessage(itemsError);
      logger.error('Submission items fetch failed', {
        action: 'detect_photo_changes',
        submissionId,
        error: errorMessage
      });
    } else if (submissionItems && submissionItems.length > 0) {
      for (const item of submissionItems) {
        // For photo items, data is stored differently
        // Skip for now as photo submissions use separate table
        continue;
      }
    }
  } catch (err: unknown) {
    const errorMessage = getErrorMessage(err);
    logger.error('Photo change detection failed', {
      action: 'detect_photo_changes',
      submissionId,
      error: errorMessage
    });
  }

  return changes;
}

/**
 * Detects what changed between original_data and item_data
 */
export async function detectChanges(
  item: { item_data?: any; original_data?: any; item_type: string; action_type?: string },
  submissionId?: string
): Promise<ChangesSummary> {
  const itemData = item.item_data || {};
  const originalData = item.original_data || {};
  
  // Determine action type - prioritize explicit action_type field to preserve submission intent
  let action: 'create' | 'edit' | 'delete' = 'edit';
  
  if (item.item_type === 'photo_delete' || itemData.action === 'delete' || itemData.deleted) {
    action = 'delete';
  } else if (item.action_type) {
    // Use explicit action_type if set (preserves original submission intent even after moderator edits)
    action = item.action_type as 'create' | 'edit' | 'delete';
  } else if (!originalData || Object.keys(originalData).length === 0) {
    // Fall back to inference for backwards compatibility
    action = 'create';
  }

  const fieldChanges: FieldChange[] = [];
  const imageChanges: ImageChange[] = [];
  let hasLocationChange = false;

  if (action === 'create') {
    // Check if this creation was edited by a moderator
    const hasModeratorEdits = originalData && Object.keys(originalData).length > 0;
    
    if (hasModeratorEdits) {
      // Compare item_data with original_data to detect moderator changes
      const allKeys = new Set([
        ...Object.keys(itemData),
        ...Object.keys(originalData)
      ]);
      
      allKeys.forEach(key => {
        if (!shouldTrackField(key)) return;
        
        const oldValue = originalData[key];
        const newValue = itemData[key];
        
        // Skip if both are empty
        const oldEmpty = oldValue === null || oldValue === undefined || oldValue === '';
        const newEmpty = newValue === null || newValue === undefined || newValue === '';
        
        if (oldEmpty && newEmpty) return;
        
        // Detect the type of change
        if (!isEqual(oldValue, newValue)) {
          fieldChanges.push({
            field: key,
            oldValue,
            newValue,
            changeType: oldEmpty && !newEmpty ? 'added' :    // Moderator added new field
                       newEmpty && !oldEmpty ? 'removed' :   // Moderator removed field
                       'modified',                           // Moderator changed value
          });
        } else if (!newEmpty) {
          // Field unchanged - show as 'added' (part of original submission)
          fieldChanges.push({
            field: key,
            oldValue: null,
            newValue,
            changeType: 'added',
          });
        }
      });
    } else {
      // No moderator edits - show all fields as 'added' (original behavior)
      Object.entries(itemData).forEach(([key, value]) => {
        const systemFields = ['id', 'created_at', 'updated_at', 'slug', 'images', 'image_assignments'];
        const shouldShow = !systemFields.includes(key) && value !== null && value !== undefined && value !== '';
        
        if (shouldShow) {
          fieldChanges.push({
            field: key,
            oldValue: null,
            newValue: value,
            changeType: 'added',
          });
        }
      });
    }
  } else if (action === 'edit') {
    // Compare each field
    const allKeys = new Set([
      ...Object.keys(itemData),
      ...Object.keys(originalData)
    ]);

    allKeys.forEach(key => {
      if (!shouldTrackField(key)) return;

      const oldValue = originalData[key];
      const newValue = itemData[key];

      // Handle location changes specially - compare objects not IDs
      if (key === 'location' || key === 'location_id') {
        // Skip location_id if we already have a location object
        if (key === 'location_id' && itemData.location) {
          return;
        }
        
        const oldLoc = originalData.location;
        const newLoc = itemData.location;
        
        // Check if new location entity is being created (old has location_id, new has location object)
        const isCreatingNewLocation = originalData.location_id && newLoc && typeof newLoc === 'object' && !oldLoc;
        
        // Only compare if we have location objects with actual data
        if (newLoc && typeof newLoc === 'object' && oldLoc && typeof oldLoc === 'object') {
          // Compare all location data including coordinates
          const locChanged = 
            oldLoc.city !== newLoc.city ||
            oldLoc.state_province !== newLoc.state_province ||
            oldLoc.country !== newLoc.country ||
            oldLoc.postal_code !== newLoc.postal_code ||
            Number(oldLoc.latitude) !== Number(newLoc.latitude) ||
            Number(oldLoc.longitude) !== Number(newLoc.longitude);
          
          if (locChanged) {
            hasLocationChange = true;
            fieldChanges.push({
              field: 'location',
              oldValue: oldLoc,
              newValue: newLoc,
              changeType: 'modified',
            });
          }
        } else if (isCreatingNewLocation) {
          // New location entity is being created - mark as location change
          hasLocationChange = true;
          fieldChanges.push({
            field: 'location',
            oldValue: { location_id: originalData.location_id },
            newValue: newLoc,
            changeType: 'modified',
            metadata: { isCreatingNewLocation: true },
          });
        }
        return;
      }

      // Skip if both are "empty" (null, undefined, or empty string)
      const oldEmpty = oldValue === null || oldValue === undefined || oldValue === '';
      const newEmpty = newValue === null || newValue === undefined || newValue === '';

      if (oldEmpty && newEmpty) {
        return; // Both empty, no change
      }

      // Check for changes
      if (!isEqual(oldValue, newValue)) {
        const fieldChange: FieldChange = {
          field: key,
          oldValue,
          newValue,
          changeType: oldEmpty && !newEmpty ? 'added' : 
                     newEmpty && !oldEmpty ? 'removed' : 
                     'modified',
        };
        
        // Add precision metadata for date fields
        if (key.endsWith('_date') && !key.endsWith('_precision')) {
          const precisionKey = `${key}_precision`;
          const newPrecision = itemData[precisionKey];
          const oldPrecision = originalData[precisionKey];
          
          if (newPrecision || oldPrecision) {
            fieldChange.metadata = {
              ...fieldChange.metadata,
              precision: newPrecision || oldPrecision,
              oldPrecision,
              newPrecision,
            };
          }
        }
        
        fieldChanges.push(fieldChange);
      }
    });

    // Detect image changes
    detectImageChanges(originalData, itemData, imageChanges);
  }

  // Get entity name - handle different item types
  let entityName = 'Unknown';
  if (item.item_type === 'photo_delete' || item.item_type === 'photo_edit' || item.item_type === 'photo') {
    // For photo operations, prioritize entity_name from item_data
    entityName = itemData.entity_name || itemData.caption || itemData.title || 'Photo';
    
    // If we have entity_type and entity_id but no entity_name, fetch it from DB
    if (!itemData.entity_name && itemData.entity_type && itemData.entity_id) {
      try {
        const entityType = itemData.entity_type;
        const entityId = itemData.entity_id;
        
        if (entityType === 'park') {
          const { data } = await supabase.from('parks').select('name').eq('id', entityId).maybeSingle();
          if (data?.name) entityName = `${data.name} (${formatEntityType(entityType)})`;
        } else if (entityType === 'ride') {
          const { data } = await supabase.from('rides').select('name').eq('id', entityId).maybeSingle();
          if (data?.name) entityName = `${data.name} (${formatEntityType(entityType)})`;
        } else if (entityType === 'ride_model') {
          const { data } = await supabase.from('ride_models').select('name').eq('id', entityId).maybeSingle();
          if (data?.name) entityName = `${data.name} (${formatEntityType(entityType)})`;
        } else if (['manufacturer', 'operator', 'designer', 'property_owner'].includes(entityType)) {
          const { data } = await supabase.from('companies').select('name').eq('id', entityId).maybeSingle();
          if (data?.name) entityName = `${data.name} (${formatEntityType(entityType)})`;
        }
      } catch (err) {
        console.error('Error fetching entity name for photo operation:', err);
      }
    }
    
    // Add debugging warning if critical data is missing
    if (!itemData.entity_name && item.item_type === 'photo_delete') {
      logger.warn('[Photo Delete] Missing entity_name for photo_delete item', {
        item_type: item.item_type,
        has_entity_type: !!itemData.entity_type,
        has_entity_id: !!itemData.entity_id,
        has_cloudflare_url: !!itemData.cloudflare_image_url
      });
    }
  } else if (item.item_type === 'milestone') {
    // Milestone submissions reference entity_id and entity_type
    // Need to fetch the entity name from the database
    if (itemData.entity_type && itemData.entity_id) {
      try {
        const entityType = itemData.entity_type;
        const entityId = itemData.entity_id;
        
        if (entityType === 'park') {
          const { data } = await supabase.from('parks').select('name').eq('id', entityId).maybeSingle();
          if (data?.name) {
            entityName = `${data.name} - ${itemData.title || 'Milestone'}`;
          }
        } else if (entityType === 'ride') {
          const { data: rideData } = await supabase
            .from('rides')
            .select('name, park:parks(name)')
            .eq('id', entityId)
            .maybeSingle();
          
          if (rideData?.name) {
            const parkName = rideData.park?.name;
            entityName = parkName 
              ? `${rideData.name} at ${parkName} - ${itemData.title || 'Milestone'}`
              : `${rideData.name} - ${itemData.title || 'Milestone'}`;
          }
        }
        
        // If lookup failed, fall back to title with entity type
        if (entityName === 'Unknown' && itemData.title) {
          entityName = `${formatEntityType(entityType)} - ${itemData.title}`;
        }
      } catch (err) {
        console.error('Error fetching entity name for milestone:', err);
        // Fall back to just the title if database lookup fails
        if (itemData.title) {
          entityName = itemData.title;
        }
      }
    } else if (itemData.title) {
      // No entity reference, just use the milestone title
      entityName = itemData.title;
    }
    
    // Add resolved entity name as an explicit field for milestone submissions
    if (itemData.entity_type && itemData.entity_id) {
      let resolvedEntityName = 'Unknown Entity';
      
      try {
        const entityType = itemData.entity_type;
        const entityId = itemData.entity_id;
        
        if (entityType === 'park') {
          const { data } = await supabase.from('parks').select('name').eq('id', entityId).maybeSingle();
          if (data?.name) {
            resolvedEntityName = data.name;
          }
        } else if (entityType === 'ride') {
          const { data: rideData } = await supabase
            .from('rides')
            .select('name, park:parks(name)')
            .eq('id', entityId)
            .maybeSingle();
          
          if (rideData?.name) {
            const parkName = rideData.park?.name;
            resolvedEntityName = parkName 
              ? `${rideData.name} at ${parkName}`
              : rideData.name;
          }
        }
      } catch (err) {
        console.error('Error resolving entity name for field display:', err);
      }
      
      // Add entity name as an explicit field change at the beginning
      fieldChanges.unshift({
        field: 'entity_name',
        oldValue: null,
        newValue: resolvedEntityName,
        changeType: 'added',
      });
    }
  } else {
    // For regular entities, use name field
    entityName = itemData.name || originalData?.name || 'Unknown';
  }

  // Detect photo changes if submissionId provided
  const photoChanges = submissionId ? await detectPhotoChanges(submissionId) : [];

  return {
    action,
    entityType: item.item_type,
    entityName,
    fieldChanges,
    imageChanges,
    photoChanges,
    hasLocationChange,
    totalChanges: fieldChanges.length + imageChanges.length + photoChanges.length + (hasLocationChange ? 1 : 0)
  };
}

/**
 * ═══════════════════════════════════════════════════════════════════
 * TYPE-SAFE CHANGE EXTRACTION FOR EDIT SUBMISSIONS
 * ═══════════════════════════════════════════════════════════════════
 * 
 * Extracts ONLY changed fields from form data compared to original entity data.
 * Critical for edit operations to avoid passing unchanged fields through moderation.
 * 
 * Benefits:
 * ✅ Clearer audit trail (only see actual changes)
 * ✅ Smaller database writes (no unnecessary updates)
 * ✅ Correct validation (unchanged required fields stay in original_data)
 * ✅ Type-safe with generics (compiler catches errors)
 * ✅ Follows project knowledge: "only funnel through real changes"
 * 
 * @param formData - New form data from user submission
 * @param originalData - Original entity data from database
 * @returns Object containing ONLY changed fields
 * 
 * @example
 * // Edit that only changes description
 * extractChangedFields(
 *   { name: "Cedar Point", description: "New desc" },
 *   { name: "Cedar Point", description: "Old desc", location_id: "uuid-123" }
 * )
 * // Returns: { description: "New desc" }
 * // ✅ location_id NOT included (unchanged, exists in original_data)
 */
export function extractChangedFields<T extends Record<string, any>>(
  formData: T,
  originalData: Partial<T>
): Partial<T> {
  const changes: Partial<T> = {};
  
  // Critical IDs that MUST always be included for relational integrity
  // Even if "unchanged", these maintain foreign key relationships
  const alwaysIncludeIds = [
    'park_id',           // Rides belong to parks
    'ride_id',           // For ride updates
    'company_id',        // For company updates
    'manufacturer_id',   // Rides reference manufacturers
    'ride_model_id',     // Rides reference models
    'operator_id',       // Parks reference operators
    'property_owner_id', // Parks reference property owners
    'designer_id',       // Rides reference designers
  ];
  
  Object.keys(formData).forEach((key) => {
    const newValue = formData[key];
    const oldValue = originalData[key];
    
    // Always include critical relational IDs (even if unchanged)
    if (alwaysIncludeIds.includes(key)) {
      if (newValue !== undefined && newValue !== null) {
        changes[key as keyof T] = newValue;
      }
      return;
    }
    
    // Skip system fields and fields that shouldn't be tracked
    if (!shouldTrackField(key)) {
      return;
    }
    
    // ═══ SPECIAL HANDLING: LOCATION OBJECTS ═══
    // Location can be an object (from form) vs location_id (from DB)
    if (key === 'location' && newValue && typeof newValue === 'object') {
      const oldLoc = originalData.location;
      if (!oldLoc || typeof oldLoc !== 'object' || !isEqual(oldLoc, newValue)) {
        changes[key as keyof T] = newValue;
      }
      return;
    }
    
    // ═══ SPECIAL HANDLING: DATE FIELDS WITH PRECISION ═══
    // opening_date, closing_date, founded_date, etc.
    if (key.endsWith('_date') && !key.endsWith('_precision')) {
      const precisionKey = `${key}_precision` as keyof T;
      const newDate = newValue;
      const oldDate = oldValue;
      const newPrecision = formData[precisionKey];
      const oldPrecision = originalData[precisionKey];
      
      // Include if EITHER date OR precision changed
      if (!isEqual(newDate, oldDate) || !isEqual(newPrecision, oldPrecision)) {
        changes[key as keyof T] = newValue;
        // Also include precision if it exists
        if (newPrecision !== undefined) {
          changes[precisionKey] = newPrecision;
        }
      }
      return;
    }
    
    // Skip precision fields (they're handled with their date above)
    if (key.endsWith('_precision')) {
      return;
    }
    
    // ═══ SPECIAL HANDLING: IMAGE FIELDS ═══
    // Images have their own assignment system and should always be included if present
    if (key === 'images' || key.includes('image_')) {
      if (!isEqual(newValue, oldValue)) {
        changes[key as keyof T] = newValue;
      }
      return;
    }
    
    // ═══ GENERAL FIELD COMPARISON ═══
    // Include field if:
    // 1. Value changed from something to something else
    // 2. Value added (old was empty, new has value)
    // 
    // Do NOT include if:
    // 1. Both values are empty (null, undefined, '')
    // 2. Values are equal after normalization
    
    const oldEmpty = oldValue === null || oldValue === undefined || oldValue === '';
    const newEmpty = newValue === null || newValue === undefined || newValue === '';
    
    // If both empty, don't track (no change)
    if (oldEmpty && newEmpty) {
      return;
    }
    
    // If values differ, include the change
    if (!isEqual(oldValue, newValue)) {
      changes[key as keyof T] = newValue;
    }
  });
  
  return changes;
}

/**
 * Determines if a field should be tracked for changes
 */
function shouldTrackField(key: string): boolean {
  const excludedFields = [
    // System fields
    'id', 
    'created_at', 
    'updated_at', 
    'slug',
    
    // Image-related (handled separately)
    'images',
    'image_assignments',
    'banner_image_url',
    'banner_image_id',
    'card_image_url',
    'card_image_id',
    
    // Reference IDs (not editable, just for linking)
    'park_id',
    'ride_id',
    'company_id',
    'manufacturer_id',
    'operator_id',
    'designer_id',
    'property_owner_id',
    'location_id', // Location object is tracked instead
    
    // Computed/aggregated fields (not editable)
    'ride_count',
    'review_count',
    'coaster_count',
    'average_rating',
    
    // Analytics fields (auto-updated by system)
    'view_count_7d',
    'view_count_30d',
    'view_count_all',
  ];
  
  return !excludedFields.includes(key);
}

/**
 * Normalizes values for consistent comparison
 * Handles enum-like strings (snake_case and Title Case) by ensuring lowercase
 */
function normalizeForComparison(value: any): any {
  // Null/undefined pass through
  if (value == null) return value;
  
  // Normalize enum-like strings to lowercase for comparison
  // Matches patterns like: "operating", "Operating", "amusement_park", "Amusement_Park", "Amusement Park"
  if (typeof value === 'string' && /^[a-zA-Z_\s]+$/.test(value)) {
    return value
      .toLowerCase()
      .replace(/_/g, ' ')      // Replace underscores with spaces
      .replace(/\s+/g, ' ')    // Collapse multiple spaces
      .trim();
  }
  
  // Recursively normalize arrays
  if (Array.isArray(value)) {
    return value.map(normalizeForComparison);
  }
  
  // Recursively normalize objects (but not Date objects)
  if (typeof value === 'object' && !(value instanceof Date)) {
    const normalized: Record<string, any> = {};
    for (const [key, val] of Object.entries(value)) {
      normalized[key] = normalizeForComparison(val);
    }
    return normalized;
  }
  
  return value;
}

/**
 * Deep equality check for values with normalization
 */
function isEqual(a: any, b: any): boolean {
  // Normalize both values before comparison
  const normalizedA = normalizeForComparison(a);
  const normalizedB = normalizeForComparison(b);
  
  if (normalizedA === normalizedB) return true;
  if (normalizedA == null || normalizedB == null) return normalizedA === normalizedB;
  if (typeof normalizedA !== typeof normalizedB) return false;
  
  if (typeof normalizedA === 'object') {
    if (Array.isArray(normalizedA) && Array.isArray(normalizedB)) {
      if (normalizedA.length !== normalizedB.length) return false;
      return normalizedA.every((item, i) => isEqual(item, normalizedB[i]));
    }
    
    const keysA = Object.keys(normalizedA);
    const keysB = Object.keys(normalizedB);
    if (keysA.length !== keysB.length) return false;
    
    return keysA.every(key => isEqual(normalizedA[key], normalizedB[key]));
  }
  
  return false;
}

/**
 * Normalizes image data structures to extract IDs consistently
 */
function getImageIds(data: any): { banner?: string; card?: string } {
  const result: { banner?: string; card?: string } = {};
  
  // Handle flat structure (original_data from DB)
  if (data.banner_image_id) result.banner = data.banner_image_id;
  if (data.card_image_id) result.card = data.card_image_id;
  
  // Handle nested structure (item_data from form)
  if (data.images?.uploaded && Array.isArray(data.images.uploaded)) {
    const uploaded = data.images.uploaded;
    
    // Handle banner/card assignment mapping (default to indices 0 and 1)
    const bannerIdx = data.images.banner_assignment ?? 0;
    const cardIdx = data.images.card_assignment ?? 1;
    
    // Try both 'cloudflare_id' and 'id' for compatibility
    if (uploaded[bannerIdx]) {
      result.banner = uploaded[bannerIdx].cloudflare_id || uploaded[bannerIdx].id;
    }
    if (uploaded[cardIdx]) {
      result.card = uploaded[cardIdx].cloudflare_id || uploaded[cardIdx].id;
    }
  }
  
  return result;
}

/**
 * Detects changes in banner/card images
 */
function detectImageChanges(
  originalData: any,
  itemData: any,
  imageChanges: ImageChange[]
): void {
  // Normalize both data structures before comparing
  const oldIds = getImageIds(originalData);
  const newIds = getImageIds(itemData);
  
  // Check banner image
  if (oldIds.banner !== newIds.banner) {
    imageChanges.push({
      type: 'banner',
      oldUrl: originalData.banner_image_url,
      newUrl: itemData.banner_image_url || itemData.images?.uploaded?.[0]?.url,
      oldId: oldIds.banner,
      newId: newIds.banner,
    });
  }

  // Check card image
  if (oldIds.card !== newIds.card) {
    imageChanges.push({
      type: 'card',
      oldUrl: originalData.card_image_url,
      newUrl: itemData.card_image_url || itemData.images?.uploaded?.[1]?.url,
      oldId: oldIds.card,
      newId: newIds.card,
    });
  }
}

/**
 * Format field name for display
 */
export function formatFieldName(field: string): string {
  return field
    .replace(/_/g, ' ')
    .replace(/([A-Z])/g, ' $1')
    .replace(/^./, str => str.toUpperCase())
    .trim();
}

/**
 * Get table name for entity type
 */
function getTableNameForEntityType(entityType: string): string | null {
  const mapping: Record<string, string> = {
    'park': 'parks',
    'ride': 'rides',
    'manufacturer': 'companies',
    'operator': 'companies',
    'designer': 'companies',
    'property_owner': 'companies',
    'ride_model': 'ride_models'
  };
  return mapping[entityType] || null;
}

/**
 * Format entity type for display
 */
function formatEntityType(entityType: string): string {
  return entityType
    .split('_')
    .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
    .join(' ');
}

/**
 * Format field value for display
 */
export function formatFieldValue(value: any, precision?: 'day' | 'month' | 'year'): string {
  if (value === null || value === undefined) return 'None';
  if (typeof value === 'boolean') return value ? 'Yes' : 'No';
  
  // Handle dates with precision support
  if (value instanceof Date || (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}/.test(value))) {
    try {
      const date = new Date(value);
      
      // Apply precision if provided
      if (precision === 'year') {
        return date.getFullYear().toString();
      } else if (precision === 'month') {
        return date.toLocaleDateString('en-US', { year: 'numeric', month: 'long' });
      }
      
      // Default: full date
      return date.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' });
    } catch {
      return String(value);
    }
  }
  
  // Handle arrays - show actual items
  if (Array.isArray(value)) {
    if (value.length === 0) return 'None';
    if (value.length <= 3) return value.map(v => String(v)).join(', ');
    return `${value.slice(0, 3).map(v => String(v)).join(', ')}... +${value.length - 3} more`;
  }
  
  // Handle objects - create readable summary
  if (typeof value === 'object') {
    // Location object
    if (value.city || value.state_province || value.country) {
      const parts = [value.city, value.state_province, value.country].filter(Boolean);
      return parts.join(', ');
    }
    
    // Generic object - show key-value pairs
    const entries = Object.entries(value).slice(0, 3);
    if (entries.length === 0) return 'Empty';
    return entries.map(([k, v]) => `${k}: ${v}`).join(', ');
  }
  
  // Handle year-like numbers (prevent comma formatting for founded_year)
  if (typeof value === 'number') {
    const currentYear = new Date().getFullYear();
    if (value >= 1800 && value <= currentYear + 10) {
      return value.toString(); // Don't add commas for year values
    }
    return value.toLocaleString(); // Add commas for other numbers
  }
  
  // Handle URLs
  if (typeof value === 'string' && value.startsWith('http')) {
    try {
      const url = new URL(value);
      return url.hostname + (url.pathname !== '/' ? url.pathname.slice(0, 30) : '');
    } catch {
      return value;
    }
  }
  
  // Handle enum-like strings (snake_case or kebab-case) - capitalize and replace separators
  if (typeof value === 'string' && (value.includes('_') || value.includes('-'))) {
    return value
      .split(/[_-]/)
      .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
      .join(' ');
  }
  
  if (typeof value === 'number') return value.toLocaleString();
  return String(value);
}
