import { Badge } from '@/components/ui/badge';
import { formatFieldName, formatFieldValue } from '@/lib/submissionChangeDetection';
import type { FieldChange, ImageChange } from '@/lib/submissionChangeDetection';
import { ArrowRight } from 'lucide-react';
import { ArrayFieldDiff } from './ArrayFieldDiff';
import { SpecialFieldDisplay } from './SpecialFieldDisplay';

// Helper to format compact values (truncate long strings)
function formatCompactValue(value: unknown, precision?: 'day' | 'month' | 'year', maxLength = 30): string {
  const formatted = formatFieldValue(value, precision);
  if (formatted.length > maxLength) {
    return formatted.substring(0, maxLength) + '...';
  }
  return formatted;
}

interface FieldDiffProps {
  change: FieldChange;
  compact?: boolean;
}

export function FieldDiff({ change, compact = false }: FieldDiffProps) {
  const { field, oldValue, newValue, changeType, metadata } = change;

  // Extract precision for date fields
  const precision = metadata?.precision;
  const oldPrecision = metadata?.oldPrecision;
  const newPrecision = metadata?.newPrecision;

  // Check if this is an array field that needs special handling
  if (Array.isArray(oldValue) && Array.isArray(newValue)) {
    return (
      <ArrayFieldDiff
        fieldName={formatFieldName(field)}
        oldArray={oldValue}
        newArray={newValue}
        compact={compact}
      />
    );
  }

  // Check if this is a special field type that needs custom rendering
  const specialDisplay = SpecialFieldDisplay({ change, compact });
  if (specialDisplay) {
    return specialDisplay;
  }

  const getChangeColor = () => {
    switch (changeType) {
      case 'added': return 'text-green-600 dark:text-green-400';
      case 'removed': return 'text-red-600 dark:text-red-400';
      case 'modified': return 'text-amber-600 dark:text-amber-400';
      default: return '';
    }
  };

  if (compact) {
    const fieldName = formatFieldName(field);
    
    if (changeType === 'added') {
      return (
        <Badge variant="outline" className={getChangeColor()}>
          {fieldName}: + {formatCompactValue(newValue, precision)}
        </Badge>
      );
    }
    
    if (changeType === 'removed') {
      return (
        <Badge variant="outline" className={getChangeColor()}>
          {fieldName}: <span className="line-through">{formatCompactValue(oldValue, precision)}</span>
        </Badge>
      );
    }
    
    if (changeType === 'modified') {
      return (
        <Badge variant="outline" className={getChangeColor()}>
          {fieldName}: {formatCompactValue(oldValue, oldPrecision || precision)} → {formatCompactValue(newValue, newPrecision || precision)}
        </Badge>
      );
    }
    
    return (
      <Badge variant="outline" className={getChangeColor()}>
        {fieldName}
      </Badge>
    );
  }

  return (
    <div className="flex flex-col gap-1 p-2 rounded-md bg-muted/50">
      <div className="text-sm font-medium">{formatFieldName(field)}</div>
      
      {changeType === 'added' && (
        <div className="text-sm text-green-600 dark:text-green-400">
          + {formatFieldValue(newValue, precision)}
        </div>
      )}
      
      {changeType === 'removed' && (
        <div className="text-sm text-red-600 dark:text-red-400 line-through">
          {formatFieldValue(oldValue, precision)}
        </div>
      )}
      
      {changeType === 'modified' && (
        <div className="flex items-center gap-2 text-sm">
          <span className="text-red-600 dark:text-red-400 line-through">
            {formatFieldValue(oldValue, oldPrecision || precision)}
          </span>
          <ArrowRight className="h-3 w-3 text-muted-foreground" />
          <span className="text-green-600 dark:text-green-400">
            {formatFieldValue(newValue, newPrecision || precision)}
          </span>
        </div>
      )}
    </div>
  );
}

interface ImageDiffProps {
  change: ImageChange;
  compact?: boolean;
}

export function ImageDiff({ change, compact = false }: ImageDiffProps) {
  const { type, oldUrl, newUrl } = change;

  if (compact) {
    const imageLabel = type === 'banner' ? 'Banner' : 'Card';
    const isAddition = !oldUrl && newUrl;
    const isRemoval = oldUrl && !newUrl;
    const isReplacement = oldUrl && newUrl;
    
    let action = '';
    let colorClass = 'text-blue-600 dark:text-blue-400';
    
    if (isAddition) {
      action = ' (Added)';
      colorClass = 'text-green-600 dark:text-green-400';
    } else if (isRemoval) {
      action = ' (Removed)';
      colorClass = 'text-red-600 dark:text-red-400';
    } else if (isReplacement) {
      action = ' (Changed)';
      colorClass = 'text-amber-600 dark:text-amber-400';
    }
    
    return (
      <Badge variant="outline" className={colorClass}>
        {imageLabel} Image{action}
      </Badge>
    );
  }

  // Determine scenario
  const isAddition = !oldUrl && newUrl;
  const isRemoval = oldUrl && !newUrl;
  const isReplacement = oldUrl && newUrl;

  return (
    <div className="flex flex-col gap-2 p-3 rounded-md bg-muted/50">
      <div className="text-sm font-medium">
        {type === 'banner' ? 'Banner' : 'Card'} Image
        {isAddition && <span className="text-green-600 dark:text-green-400 ml-2">(New)</span>}
        {isRemoval && <span className="text-red-600 dark:text-red-400 ml-2">(Removed)</span>}
        {isReplacement && <span className="text-amber-600 dark:text-amber-400 ml-2">(Changed)</span>}
      </div>
      
      <div className="flex items-center gap-3">
        {oldUrl && (
          <div className="flex-1">
            <div className="text-xs text-muted-foreground mb-1">Before</div>
            <img 
              src={oldUrl} 
              alt="Previous" 
              className="w-full h-32 object-cover rounded border-2 border-red-500/50"
              loading="lazy"
            />
          </div>
        )}
        
        {oldUrl && newUrl && (
          <ArrowRight className="h-5 w-5 text-muted-foreground flex-shrink-0" />
        )}
        
        {newUrl && (
          <div className="flex-1">
            <div className="text-xs text-muted-foreground mb-1">{isAddition ? 'New Image' : 'After'}</div>
            <img 
              src={newUrl} 
              alt="New" 
              className="w-full h-32 object-cover rounded border-2 border-green-500/50"
              loading="lazy"
            />
          </div>
        )}
      </div>
    </div>
  );
}

interface LocationData {
  location_id?: string;
  city?: string;
  state_province?: string;
  country?: string;
  postal_code?: string;
  latitude?: number | string;
  longitude?: number | string;
}

interface LocationDiffProps {
  oldLocation: LocationData | string | null | undefined;
  newLocation: LocationData | string | null | undefined;
  compact?: boolean;
}

export function LocationDiff({ oldLocation, newLocation, compact = false }: LocationDiffProps) {
  // Type guards for LocationData
  const isLocationData = (loc: unknown): loc is LocationData => {
    return typeof loc === 'object' && loc !== null && !Array.isArray(loc);
  };

  // Check if we're creating a new location entity
  const isCreatingNewLocation = isLocationData(oldLocation) && 
    oldLocation.location_id && 
    !oldLocation.city && 
    isLocationData(newLocation) && 
    newLocation.city;
  
  const formatLocation = (loc: LocationData | string | null | undefined) => {
    if (!loc) return 'None';
    if (typeof loc === 'string') return loc;
    
    // Handle location_id reference
    if (loc.location_id && !loc.city) {
      return `Location ID: ${loc.location_id.substring(0, 8)}...`;
    }
    
    if (typeof loc === 'object') {
      const parts: string[] = [];
      if (loc.city) parts.push(String(loc.city));
      if (loc.state_province) parts.push(String(loc.state_province));
      if (loc.country && loc.country !== loc.state_province) parts.push(String(loc.country));
      if (loc.postal_code) parts.push(String(loc.postal_code));
      
      let locationStr = parts.join(', ') || 'Unknown';
      
      // Add coordinates if available
      if (loc.latitude && loc.longitude) {
        const lat = Number(loc.latitude).toFixed(6);
        const lng = Number(loc.longitude).toFixed(6);
        locationStr += ` (${lat}°, ${lng}°)`;
      }
      
      return locationStr;
    }
    return String(loc);
  };

  // Check if only coordinates changed
  const onlyCoordinatesChanged = isLocationData(oldLocation) && 
    isLocationData(newLocation) &&
    oldLocation.city === newLocation.city &&
    oldLocation.state_province === newLocation.state_province &&
    oldLocation.country === newLocation.country &&
    oldLocation.postal_code === newLocation.postal_code &&
    (Number(oldLocation.latitude) !== Number(newLocation.latitude) || 
     Number(oldLocation.longitude) !== Number(newLocation.longitude));

  if (compact) {
    const oldLoc = formatLocation(oldLocation);
    const newLoc = formatLocation(newLocation);
    
    if (!oldLocation && newLocation) {
      return (
        <Badge variant="outline" className="text-green-600 dark:text-green-400">
          Location: + {newLoc}
        </Badge>
      );
    }
    
    if (oldLocation && !newLocation) {
      return (
        <Badge variant="outline" className="text-red-600 dark:text-red-400">
          Location: <span className="line-through">{oldLoc}</span>
        </Badge>
      );
    }
    
    return (
      <Badge variant="outline" className="text-amber-600 dark:text-amber-400">
        Location{isCreatingNewLocation && ' (New Entity)'}
        {onlyCoordinatesChanged && ' (GPS Refined)'}
        : {oldLoc} → {newLoc}
      </Badge>
    );
  }

  return (
    <div className="flex flex-col gap-1 p-2 rounded-md bg-muted/50">
      <div className="text-sm font-medium">
        Location
        {isCreatingNewLocation && (
          <Badge variant="secondary" className="ml-2">New location entity</Badge>
        )}
        {onlyCoordinatesChanged && (
          <Badge variant="outline" className="ml-2">GPS coordinates refined</Badge>
        )}
      </div>
      
      <div className="flex items-center gap-2 text-sm">
        {oldLocation && (
          <span className="text-red-600 dark:text-red-400 line-through">
            {formatLocation(oldLocation)}
          </span>
        )}
        {oldLocation && newLocation && (
          <ArrowRight className="h-3 w-3 text-muted-foreground" />
        )}
        {newLocation && (
          <span className="text-green-600 dark:text-green-400">
            {formatLocation(newLocation)}
          </span>
        )}
      </div>
    </div>
  );
}
