import { useMutation } from '@apollo/client/react';
import { gql } from '@apollo/client';
import { PROFILE_QUERY } from '../api/operations/queries';
import {
  DEVICE_LOCATION_UPDATE_MUTATION,
  UNDO_PROFILE_DISLIKE_MUTATION,
  PROFILE_ACCEPT_PING_MUTATION,
  PROFILE_REJECT_PING_MUTATION,
  FILTERED_WHO_LIKES_ME_MUTATION,
  FILTERED_WHO_PINGS_ME_MUTATION,
} from '../api/operations/mutations';
import { PAST_LIKES_QUERY, PAST_DISLIKES_QUERY } from '../api/operations/experimental';
import { ProfileCard } from '../components/profile/ProfileCard';
import { ProfileDetailModal } from '../components/profile/ProfileDetailModal';
import { LoadingPage, LoadingCards } from '../components/ui/Loading';
import { useState, useEffect, useCallback, useMemo, useRef } from 'react';
import { useDislikedProfiles } from '../hooks/useDislikedProfiles';
import { useFavorites } from '../hooks/useFavorites';
import { apolloClient } from '../api/client';
import { useLocation } from '../hooks/useLocation';
import { isCountryBanned, findBannedCountry } from '../config/bannedCountries';
import * as dataSync from '../api/dataSync';

// Same query as Discover's load more - includes alreadyShownProfileIDs support
const SCAN_PROFILES_QUERY = gql`
  query ScanProfiles($input: ProfileDiscoveryInput!) {
    discovery(input: $input) {
      nodes {
        id
        age
        imaginaryName
        gender
        sexuality
        isIncognito
        isMajestic
        verificationStatus
        connectionGoals
        desires
        bio
        interests
        distance { km mi __typename }
        photos {
          id
          pictureUrls { small medium large __typename }
          pictureType
          __typename
        }
        interactionStatus { message mine theirs __typename }
        __typename
      }
      hasNextBatch
      __typename
    }
  }
`;

const styles = {
  container: {
    paddingBottom: '48px',
  },

  // Header
  header: {
    marginBottom: '32px',
  },
  title: {
    fontFamily: "'Clash Display', sans-serif",
    fontSize: '36px',
    fontWeight: 700,
    color: '#ffffff',
    margin: 0,
    marginBottom: '8px',
    letterSpacing: '-0.02em',
  },
  subtitle: {
    fontFamily: "'Satoshi', sans-serif",
    fontSize: '15px',
    color: 'rgba(255,255,255,0.5)',
    margin: 0,
  },

  // Tabs
  tabContainer: {
    display: 'flex',
    gap: '12px',
    marginBottom: '32px',
  },
  tab: (isActive: boolean, variant: 'likes' | 'pings' | 'youLiked' | 'disliked' | 'saved') => {
    const gradients: Record<string, string> = {
      likes: 'linear-gradient(135deg, #be3144 0%, #c41e3a 100%)',
      pings: 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)',
      youLiked: 'linear-gradient(135deg, #22c55e 0%, #16a34a 100%)',
      disliked: 'linear-gradient(135deg, #64748b 0%, #475569 100%)',
      saved: 'linear-gradient(135deg, #a855f7 0%, #7c3aed 100%)',
    };
    return {
      display: 'flex',
      alignItems: 'center',
      gap: '10px',
      padding: '14px 24px',
      borderRadius: '14px',
      fontSize: '14px',
      fontWeight: 600,
      fontFamily: "'Satoshi', sans-serif",
      border: 'none',
      background: isActive ? gradients[variant] : 'rgba(255,255,255,0.03)',
      color: isActive ? '#ffffff' : 'rgba(255,255,255,0.7)',
      cursor: 'pointer',
      transition: 'all 0.2s ease',
      boxShadow: isActive ? '0 4px 20px rgba(0,0,0,0.3)' : 'none',
    };
  },
  tabBadge: (isActive: boolean, variant: 'likes' | 'pings' | 'youLiked' | 'disliked' | 'saved') => {
    const colors: Record<string, { bg: string; color: string }> = {
      likes: { bg: 'rgba(190,49,68,0.25)', color: '#f4a5b0' },
      pings: { bg: 'rgba(245,158,11,0.25)', color: '#fcd34d' },
      youLiked: { bg: 'rgba(34,197,94,0.25)', color: '#86efac' },
      disliked: { bg: 'rgba(100,116,139,0.25)', color: '#94a3b8' },
      saved: { bg: 'rgba(168,85,247,0.25)', color: '#d8b4fe' },
    };
    return {
      padding: '4px 10px',
      borderRadius: '20px',
      fontSize: '12px',
      fontWeight: 700,
      fontFamily: "'Satoshi', sans-serif",
      background: isActive ? 'rgba(255,255,255,0.2)' : colors[variant].bg,
      color: isActive ? '#ffffff' : colors[variant].color,
    };
  },

  // Grid
  profileGrid: {
    display: 'grid',
    gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))',
    gap: '16px',
  },

  // Empty state
  emptyState: {
    display: 'flex',
    flexDirection: 'column' as const,
    alignItems: 'center',
    justifyContent: 'center',
    padding: '80px 20px',
  },
  emptyIcon: (variant: 'likes' | 'pings' | 'youLiked' | 'disliked' | 'saved') => {
    const backgrounds: Record<string, string> = {
      likes: 'linear-gradient(135deg, rgba(190,49,68,0.15) 0%, rgba(190,49,68,0.05) 100%)',
      pings: 'linear-gradient(135deg, rgba(245,158,11,0.15) 0%, rgba(245,158,11,0.05) 100%)',
      youLiked: 'linear-gradient(135deg, rgba(34,197,94,0.15) 0%, rgba(34,197,94,0.05) 100%)',
      disliked: 'linear-gradient(135deg, rgba(100,116,139,0.15) 0%, rgba(100,116,139,0.05) 100%)',
      saved: 'linear-gradient(135deg, rgba(168,85,247,0.15) 0%, rgba(168,85,247,0.05) 100%)',
    };
    return {
      width: '80px',
      height: '80px',
      borderRadius: '50%',
      background: backgrounds[variant],
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      marginBottom: '24px',
    };
  },
  emptyTitle: {
    fontFamily: "'Clash Display', sans-serif",
    fontSize: '22px',
    fontWeight: 600,
    color: '#ffffff',
    marginBottom: '8px',
    textAlign: 'center' as const,
  },
  emptyText: {
    fontFamily: "'Satoshi', sans-serif",
    fontSize: '15px',
    color: 'rgba(255,255,255,0.5)',
    textAlign: 'center' as const,
    maxWidth: '280px',
  },

  // Scanner controls
  scannerContainer: {
    display: 'flex',
    alignItems: 'center',
    gap: '12px',
    marginBottom: '24px',
    padding: '16px',
    borderRadius: '12px',
    background: 'rgba(255,255,255,0.03)',
    border: '1px solid rgba(255,255,255,0.06)',
  },
  locationSelect: {
    flex: 1,
    padding: '12px 16px',
    borderRadius: '8px',
    border: '1px solid rgba(255,255,255,0.1)',
    background: 'rgba(255,255,255,0.05)',
    color: '#fff',
    fontSize: '14px',
    fontFamily: "'Satoshi', sans-serif",
    cursor: 'pointer',
    outline: 'none',
  },
  scanButton: (isScanning: boolean) => ({
    display: 'flex',
    alignItems: 'center',
    gap: '8px',
    padding: '12px 20px',
    borderRadius: '8px',
    border: 'none',
    background: isScanning ? 'rgba(245,158,11,0.2)' : 'linear-gradient(135deg, #22c55e 0%, #16a34a 100%)',
    color: '#fff',
    fontSize: '14px',
    fontWeight: 600,
    fontFamily: "'Satoshi', sans-serif",
    cursor: isScanning ? 'not-allowed' : 'pointer',
    opacity: isScanning ? 0.7 : 1,
    transition: 'all 0.2s ease',
    whiteSpace: 'nowrap' as const,
  }),
  scanStatus: {
    fontSize: '13px',
    color: 'rgba(255,255,255,0.6)',
    marginTop: '8px',
  },
  foundBadge: {
    display: 'inline-flex',
    alignItems: 'center',
    gap: '4px',
    padding: '4px 8px',
    borderRadius: '6px',
    background: 'rgba(34,197,94,0.2)',
    color: '#86efac',
    fontSize: '12px',
    fontWeight: 600,
    marginLeft: '8px',
  },
};

// Haversine distance in miles between two lat/lng points
function distanceMiles(lat1: number, lng1: number, lat2: number, lng2: number): number {
  const R = 3959; // Earth radius in miles
  const dLat = (lat2 - lat1) * Math.PI / 180;
  const dLng = (lng2 - lng1) * Math.PI / 180;
  const a = Math.sin(dLat / 2) ** 2 +
    Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
    Math.sin(dLng / 2) ** 2;
  return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
}

// Deduplicate locations: remove exact dupes and locations whose coverage overlaps
function deduplicateLocations(locations: { name: string; latitude: number; longitude: number }[], scanRadiusMiles: number) {
  const kept: typeof locations = [];
  const skipped: string[] = [];

  for (const loc of locations) {
    // Skip if another kept location already covers this area
    const coveredBy = kept.find(k =>
      distanceMiles(k.latitude, k.longitude, loc.latitude, loc.longitude) < scanRadiusMiles * 0.5
    );
    if (coveredBy) {
      skipped.push(`${loc.name} (covered by ${coveredBy.name})`);
      continue;
    }
    kept.push(loc);
  }

  return { kept, skipped };
}

// Shared scan logic: scan a single location, returning profiles found
async function scanLocationBatches(opts: {
  location: { latitude: number; longitude: number; name: string };
  maxDistance: number;
  alreadyShownProfileIDs: string[];
  maxBatches: number;
  onBatch: (batch: number, profiles: any[], totalSoFar: number, matchesSoFar: number) => void;
  onMatch: (profile: any, locationName: string) => Promise<void>;
  signal?: AbortSignal;
}): Promise<{ profiles: any[]; matches: number }> {
  const { location, maxDistance, alreadyShownProfileIDs, maxBatches, onBatch, onMatch, signal } = opts;
  let matchCount = 0;
  const allProfiles: any[] = [];
  let hasNextBatch = true;
  let batch = 0;

  while (hasNextBatch && batch < maxBatches) {
    if (signal?.aborted) break;
    batch++;

    const result = await apolloClient.query({
      query: SCAN_PROFILES_QUERY,
      variables: {
        input: {
          filters: {
            ageRange: [18, 99],
            maxDistance,
            lookingFor: ['WOMAN', 'MAN', 'MAN_WOMAN_COUPLE', 'WOMAN_WOMAN_COUPLE', 'MAN_MAN_COUPLE', 'NON_BINARY'],
            recentlyOnline: false,
            desiringFor: [],
            alreadyShownProfileIDs,
          },
        },
      },
      fetchPolicy: 'no-cache',
    });

    const profiles = result.data?.discovery?.nodes || [];
    hasNextBatch = result.data?.discovery?.hasNextBatch ?? false;

    // Track shown IDs (shared across locations in Fuck It mode)
    profiles.forEach((p: any) => alreadyShownProfileIDs.push(p.id));
    allProfiles.push(...profiles);

    // Check for profiles that liked us
    for (const profile of profiles) {
      if (profile.interactionStatus?.theirs === 'LIKED') {
        matchCount++;
        await onMatch(profile, location.name);
      }
    }

    onBatch(batch, profiles, allProfiles.length, matchCount);

    if (hasNextBatch) {
      await new Promise(resolve => setTimeout(resolve, 300));
    }
  }

  return { profiles: allProfiles, matches: matchCount };
}

type Tab = 'likes' | 'pings' | 'youLiked' | 'disliked' | 'saved';

interface WhoLikedYouProfile {
  id: string;
  imaginaryName: string;
  age: number;
  gender: string;
  sexuality: string;
  bio?: string;
  desires?: string[];
  connectionGoals?: string[];
  verificationStatus?: string;
  distance?: { km: number; mi: number };
  photos?: any[];
  discoveredAt: string;
  location?: string;
}

export function LikesPage() {
  const [activeTab, setActiveTab] = useState<Tab>('likes');
  const [selectedProfileId, setSelectedProfileId] = useState<string | null>(null);

  // Saved-for-later (favorites) tab data
  const { favorites, removeFavorite } = useFavorites();

  // Flatten favorites to profile objects for the grid (preferring enriched
  // profile data when available, falling back to the saved snapshot).
  // Declared near the hook so it stays above any early-return paths below
  // — Rules of Hooks: same order every render.
  const savedProfiles = useMemo(
    () =>
      favorites
        .map((f) => f.profile)
        .filter((p): p is NonNullable<typeof p> => !!p),
    [favorites],
  );

  // Scanner state
  const [selectedLocationId, setSelectedLocationId] = useState<string>('');
  const [isScanning, setIsScanning] = useState(false);
  const [scanStatus, setScanStatus] = useState<string>('');
  const [whoLikedYouProfiles, setWhoLikedYouProfiles] = useState<WhoLikedYouProfile[]>([]);

  // "Fuck It" multi-location scan state
  const [isFuckItScanning, setIsFuckItScanning] = useState(false);
  const [fuckItProgress, setFuckItProgress] = useState({ current: 0, total: 0, currentLocation: '', totalProfiles: 0, totalMatches: 0 });
  const scanAbortRef = useRef<AbortController | null>(null);

  // Track which profiles are currently refreshing
  const [refreshingProfiles, setRefreshingProfiles] = useState<Set<string>>(new Set());

  // Paginated likes/pings data
  const [allLikes, setAllLikes] = useState<any[]>([]);
  const [allPings, setAllPings] = useState<any[]>([]);
  const [likesTotal, setLikesTotal] = useState(0);
  const [pingsTotal, setPingsTotal] = useState(0);
  const [likesLoading, setLikesLoading] = useState(true);
  const [pingsLoading, setPingsLoading] = useState(true);

  const { savedLocations, setLocation } = useLocation();
  const [updateLocation] = useMutation(DEVICE_LOCATION_UPDATE_MUTATION);

  const { dislikeProfile, isDisliked } = useDislikedProfiles();

  // Track which profiles are currently being disliked
  const [dislikingProfiles, setDislikingProfiles] = useState<Set<string>>(new Set());

  // Past Likes (You Liked tab - from API)
  const [pastLikes, setPastLikes] = useState<any[]>([]);
  const [pastLikesLoading, setPastLikesLoading] = useState(false);
  const [pastLikesTotal, setPastLikesTotal] = useState(0);
  const [pastLikesCursor, setPastLikesCursor] = useState<string | null>(null);
  const [pastLikesHasMore, setPastLikesHasMore] = useState(false);

  // Past Dislikes (Passed tab - from API)
  const [pastDislikes, setPastDislikes] = useState<any[]>([]);
  const [pastDislikesLoading, setPastDislikesLoading] = useState(false);
  const [pastDislikesTotal, setPastDislikesTotal] = useState(0);
  const [pastDislikesCursor, setPastDislikesCursor] = useState<string | null>(null);
  const [pastDislikesHasMore, setPastDislikesHasMore] = useState(false);

  // Undo dislike state
  const [undoLoading, setUndoLoading] = useState(false);
  const [undoError, setUndoError] = useState<string | null>(null);

  // Ping accept/reject state
  const [pingActionLoading, setPingActionLoading] = useState<Set<string>>(new Set());
  const [pingMatched, setPingMatched] = useState<Set<string>>(new Set());

  // Discovered profiles cache (all profiles seen in Discover, without photos)
  const [discoveredProfiles, setDiscoveredProfiles] = useState<any[]>([]);

  // Fetch whoLikedYou + discovered profiles from backend on mount
  useEffect(() => {
    const fetchWhoLikedYou = async () => {
      try {
        const response = await fetch('/api/who-liked-you');
        const data = await response.json();
        setWhoLikedYouProfiles(data.profiles || []);
      } catch (e) {
        console.error('Failed to fetch whoLikedYou:', e);
      }
    };
    const fetchDiscoveredProfiles = async () => {
      try {
        const response = await fetch('/api/discovered-profiles');
        const data = await response.json();
        setDiscoveredProfiles(data.profiles || []);
        console.log('Loaded discovered profiles cache:', (data.profiles || []).length);
      } catch (e) {
        console.error('Failed to fetch discovered profiles:', e);
      }
    };
    fetchWhoLikedYou();
    fetchDiscoveredProfiles();
  }, []);

  // Fetch all pages of likes via FilteredWhoLikesMe (mutation, not a query —
  // this is what the live app uses; the old WhoLikesMe query path is gone).
  const fetchAllLikes = useCallback(async () => {
    setLikesLoading(true);
    const allNodes: any[] = [];
    let cursor: string | null = null;
    let hasMore = true;
    let total = 0;

    try {
      while (hasMore) {
        const result: any = await apolloClient.mutate({
          mutation: FILTERED_WHO_LIKES_ME_MUTATION,
          variables: {
            input: { filters: { ageRange: false }, sortBy: 'LAST_INTERACTION' },
            cursor,
          },
          fetchPolicy: 'network-only',
        });

        const profiles = result.data?.filteredWhoLikesMe?.profiles;
        const nodes = profiles?.nodes || [];
        const pageInfo = profiles?.pageInfo;

        allNodes.push(...nodes);
        total = pageInfo?.total || allNodes.length;
        hasMore = pageInfo?.hasNextPage || false;
        cursor = pageInfo?.nextPageCursor || null;

        console.log(`Fetched ${nodes.length} likes, total so far: ${allNodes.length}/${total}, hasMore: ${hasMore}`);
      }

      setAllLikes(allNodes);
      setLikesTotal(total);
    } catch (e) {
      console.error('Failed to fetch likes:', e);
    } finally {
      setLikesLoading(false);
    }
  }, []);

  // Fetch all pages of pings via FilteredWhoPingsMe (mutation).
  const fetchAllPings = useCallback(async () => {
    setPingsLoading(true);
    const allNodes: any[] = [];
    let cursor: string | null = null;
    let hasMore = true;
    let total = 0;

    try {
      while (hasMore) {
        const result: any = await apolloClient.mutate({
          mutation: FILTERED_WHO_PINGS_ME_MUTATION,
          variables: {
            input: { filters: { ageRange: false }, sortBy: 'LAST_INTERACTION' },
            cursor,
          },
          fetchPolicy: 'network-only',
        });

        const profiles = result.data?.filteredWhoPingsMe?.profiles;
        const nodes = profiles?.nodes || [];
        const pageInfo = profiles?.pageInfo;

        allNodes.push(...nodes);
        total = pageInfo?.total || allNodes.length;
        hasMore = pageInfo?.hasNextPage || false;
        cursor = pageInfo?.nextPageCursor || null;

        console.log(`Fetched ${nodes.length} pings, total so far: ${allNodes.length}, hasMore: ${hasMore}`);
      }

      setAllPings(allNodes);
      setPingsTotal(total);
    } catch (e) {
      console.error('Failed to fetch pings:', e);
    } finally {
      setPingsLoading(false);
    }
  }, []);

  // Initial fetch
  useEffect(() => {
    fetchAllLikes();
    fetchAllPings();
  }, [fetchAllLikes, fetchAllPings]);

  // Helper: batch-save discovered profiles to cache (strips photos, fire-and-forget)
  const saveDiscoveredProfiles = useCallback(async (profiles: any[], discoveredLocation?: string) => {
    if (!profiles.length) return;
    const safeStr = (v: any) => (typeof v === 'string' ? v : '');
    const stripped = profiles.map(p => ({
      id: p.id,
      imaginaryName: p.imaginaryName,
      age: p.age,
      gender: safeStr(p.gender),
      sexuality: safeStr(p.sexuality),
      bio: p.bio,
      desires: p.desires,
      connectionGoals: p.connectionGoals,
      verificationStatus: p.verificationStatus,
      interactionStatus: p.interactionStatus,
      discoveredLocation: discoveredLocation ?? null,
      discoveredAt: new Date().toISOString(),
    }));
    try {
      const response = await fetch('/api/discovered-profiles/batch', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ profiles: stripped }),
      });
      if (response.ok) {
        const result = await response.json();
        console.log(`Scanner: saved ${result.added} new, ${result.updated} updated discovered profiles (${result.total} total)`);
      }
    } catch (err) {
      console.error('Failed to save discovered profiles from scanner:', err);
    }
  }, []);

  // Helper: save a matched profile to backend + local state
  const saveMatchedProfile = useCallback(async (profile: any, locationName: string) => {
    console.log('Found profile that liked us:', profile.imaginaryName, profile.id);
    const safeStr = (v: any) => typeof v === 'string' ? v : '';
    const profileData: WhoLikedYouProfile = {
      id: profile.id,
      imaginaryName: profile.imaginaryName,
      age: profile.age,
      gender: safeStr(profile.gender),
      sexuality: safeStr(profile.sexuality),
      bio: profile.bio,
      desires: profile.desires,
      connectionGoals: profile.connectionGoals,
      verificationStatus: profile.verificationStatus,
      distance: profile.distance,
      photos: profile.photos,
      discoveredAt: new Date().toISOString(),
      location: locationName,
    };

    await fetch('/api/who-liked-you', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ profile: profileData }),
    });

    setWhoLikedYouProfiles(prev => {
      if (prev.some(p => p.id === profile.id)) return prev;
      return [profileData, ...prev];
    });
  }, []);

  // Scan a single selected location
  const scanForLikes = useCallback(async () => {
    const location = savedLocations.find(l => l.id === selectedLocationId);
    if (!location) {
      setScanStatus('Please select a location first');
      return;
    }

    if (isCountryBanned(location.country, location.countryCode)) {
      const hit = findBannedCountry(location.country, location.countryCode);
      setScanStatus(`Cannot scan: Feeld is not available in ${hit?.name ?? location.country ?? 'this country'}.`);
      return;
    }

    setIsScanning(true);
    setScanStatus(`Setting location to ${location.name}...`);
    scanAbortRef.current = new AbortController();

    try {
      await updateLocation({
        variables: { input: { latitude: location.latitude, longitude: location.longitude } },
      });
      setLocation({
        latitude: location.latitude,
        longitude: location.longitude,
        name: location.name,
        country: location.country,
        countryCode: location.countryCode,
      });

      const alreadyShownProfileIDs: string[] = [];
      const { profiles, matches } = await scanLocationBatches({
        location,
        maxDistance: 400,
        alreadyShownProfileIDs,
        maxBatches: 20,
        onBatch: (batch, _profiles, totalSoFar, matchesSoFar) => {
          setScanStatus(`Scanning batch ${batch} in ${location.name}... (${totalSoFar} profiles, ${matchesSoFar} liked you)`);
        },
        onMatch: (profile) => saveMatchedProfile(profile, location.name),
        signal: scanAbortRef.current.signal,
      });

      // Save ALL scanned profiles to discovered cache for future Likes enrichment
      saveDiscoveredProfiles(profiles, location.name);

      setScanStatus(scanAbortRef.current.signal.aborted
        ? `Cancelled. Scanned ${profiles.length} profiles, found ${matches} who liked you.`
        : `Done! Scanned ${profiles.length} profiles, found ${matches} who liked you.`);
    } catch (e: any) {
      setScanStatus(`Error: ${e.message}`);
    } finally {
      setIsScanning(false);
      scanAbortRef.current = null;
    }
  }, [selectedLocationId, savedLocations, updateLocation, setLocation, saveMatchedProfile]);

  // "Fuck It" - scan ALL locations (deduplicated, cross-location dedup)
  const scanAllLocations = useCallback(async () => {
    // Strip banned-country entries before iterating — defense in depth on top of the
    // useLocation save gate and server-side filter.
    const scannable = savedLocations.filter(l => !isCountryBanned(l.country, l.countryCode));
    const skipped = savedLocations.length - scannable.length;
    if (scannable.length === 0) {
      setScanStatus(savedLocations.length === 0
        ? 'No saved locations to scan'
        : 'All saved locations are in countries where Feeld is unavailable.');
      return;
    }

    setIsFuckItScanning(true);
    scanAbortRef.current = new AbortController();
    const signal = scanAbortRef.current.signal;
    const scanRadius = 400; // miles
    const totalLocations = scannable.length;
    let grandTotalProfiles = 0;
    let grandTotalMatches = 0;

    setFuckItProgress({ current: 0, total: totalLocations, currentLocation: '', totalProfiles: 0, totalMatches: 0 });
    setScanStatus(skipped > 0
      ? `Scanning ${totalLocations} locations (skipped ${skipped} in restricted countries)...`
      : `Scanning ${totalLocations} locations...`);

    // Single shared list across ALL locations — avoids re-fetching already-seen profiles
    const alreadyShownProfileIDs: string[] = [];

    try {
      for (let locIndex = 0; locIndex < scannable.length; locIndex++) {
        if (signal.aborted) break;
        const location = scannable[locIndex];
        setFuckItProgress(prev => ({
          ...prev,
          current: locIndex + 1,
          currentLocation: location.name,
        }));

        await updateLocation({
          variables: { input: { latitude: location.latitude, longitude: location.longitude } },
        });
        setLocation({
          latitude: location.latitude,
          longitude: location.longitude,
          name: location.name,
          country: location.country,
          countryCode: location.countryCode,
        });

        try {
          const { profiles, matches } = await scanLocationBatches({
            location,
            maxDistance: scanRadius,
            alreadyShownProfileIDs,
            maxBatches: 20,
            signal,
            onBatch: (_batch, _profiles, _totalSoFar, _matchesSoFar) => {
              setFuckItProgress(prev => ({
                ...prev,
                totalProfiles: grandTotalProfiles + _totalSoFar,
                totalMatches: grandTotalMatches + _matchesSoFar,
              }));
            },
            onMatch: (profile) => saveMatchedProfile(profile, location.name),
          });

          // Save ALL scanned profiles to discovered cache
          saveDiscoveredProfiles(profiles, location.name);

          grandTotalProfiles += profiles.length;
          grandTotalMatches += matches;
        } catch (e) {
          console.error(`Scan failed for ${location.name}:`, e);
        }

        // Small delay between locations
        if (locIndex < scannable.length - 1) {
          await new Promise(resolve => setTimeout(resolve, 500));
        }
      }

      setFuckItProgress(prev => ({
        ...prev,
        current: totalLocations,
        currentLocation: 'Done!',
        totalProfiles: grandTotalProfiles,
        totalMatches: grandTotalMatches,
      }));
      setScanStatus(signal.aborted
        ? `Cancelled. ${grandTotalProfiles} profiles scanned, found ${grandTotalMatches} who liked you.`
        : `Done! ${grandTotalProfiles} unique profiles across ${totalLocations} cities, found ${grandTotalMatches} who liked you.`
      );
    } catch (e: any) {
      setScanStatus(`Error: ${e.message}`);
    } finally {
      setIsFuckItScanning(false);
      scanAbortRef.current = null;
    }
  }, [savedLocations, updateLocation, setLocation, saveMatchedProfile]);

  // Cancel any running scan
  const cancelScan = useCallback(() => {
    scanAbortRef.current?.abort();
  }, []);

  // Update backend cache with fresh photo URLs when we get them from the API
  const updateCachedPhotos = useCallback(async (realProfile: WhoLikedYouProfile, freshPhotos: any[]) => {
    if (!freshPhotos?.length) return;
    try {
      await fetch('/api/who-liked-you', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ profile: { ...realProfile, photos: freshPhotos } }),
      });
    } catch (e) {
      // Non-critical, ignore
    }
  }, []);

  // Merge whoLikedYou data with WhoLikesMe results (memoized to prevent re-renders)
  const enrichedLikes = useMemo(() => {
    if (!allLikes.length) return [];

    console.log('Enriching likes:', allLikes.length, 'with whoLikedYouProfiles:', whoLikedYouProfiles.length, 'discoveredProfiles:', discoveredProfiles.length);

    // === Pass 1: Match against whoLikedYouProfiles (has photos) ===
    // Sort real profiles by discoveredAt (oldest first) so older cached profiles get matched first
    const sortedRealProfiles = [...whoLikedYouProfiles].sort((a, b) => {
      const dateA = a.discoveredAt ? new Date(a.discoveredAt).getTime() : 0;
      const dateB = b.discoveredAt ? new Date(b.discoveredAt).getTime() : 0;
      return dateA - dateB; // Oldest first
    });

    // Track which real profiles have been matched (by their real ID)
    const matchedRealIds = new Set<string>();

    // Map from WhoLikesMe profile index to matched real profile
    // Process from END of list (oldest likes) to START (newest likes)
    // This ensures older likes get matches before newer ones with same name
    const matchMap = new Map<number, any>();

    for (let i = allLikes.length - 1; i >= 0; i--) {
      const likeProfile = allLikes[i];
      const realProfile = sortedRealProfiles.find(
        p => p.imaginaryName?.toLowerCase() === likeProfile.imaginaryName?.toLowerCase() &&
             !matchedRealIds.has(p.id)
      );

      if (realProfile) {
        matchedRealIds.add(realProfile.id);
        matchMap.set(i, realProfile);
      }
    }

    // === Pass 2: Match unmatched likes against discoveredProfiles by name only ===
    // WhoLikesMe returns fake IDs and ages, but real names. Match by name,
    // then auto-refresh will verify via ProfileQuery (checks interactionStatus.theirs === 'LIKED')
    const matchedDiscoveredIds = new Set<string>();
    const discoveryMatchMap = new Map<number, any>();

    if (discoveredProfiles.length > 0) {
      // Sort discovered by discoveredAt oldest first
      const sortedDiscovered = [...discoveredProfiles].sort((a, b) => {
        const dateA = a.discoveredAt ? new Date(a.discoveredAt).getTime() : 0;
        const dateB = b.discoveredAt ? new Date(b.discoveredAt).getTime() : 0;
        return dateA - dateB;
      });

      for (let i = allLikes.length - 1; i >= 0; i--) {
        if (matchMap.has(i)) continue; // Already matched in Pass 1

        const likeProfile = allLikes[i];
        // Name-only match — age/gender from WhoLikesMe are unreliable
        // Collect ALL candidates with same name for verification
        const candidates = sortedDiscovered.filter(
          p => p.imaginaryName?.toLowerCase() === likeProfile.imaginaryName?.toLowerCase() &&
               !matchedDiscoveredIds.has(p.id) &&
               !matchedRealIds.has(p.id)
        );

        if (candidates.length > 0) {
          // Use first candidate; auto-refresh will verify via ProfileQuery
          const discoveredProfile = candidates[0];
          matchedDiscoveredIds.add(discoveredProfile.id);
          discoveryMatchMap.set(i, {
            ...discoveredProfile,
            _allCandidateIds: candidates.map(c => c.id), // All candidates for fallback
          });
        }
      }

      if (discoveryMatchMap.size > 0) {
        console.log(`Pass 2: Matched ${discoveryMatchMap.size} additional likes from discovered cache`);
      }
    }

    // Now map in original order, using pre-computed matches
    // Merge: use real profile ID + metadata from cache, but prefer fresh photo URLs from the API
    return allLikes.map((likeProfile, index) => {
      const realProfile = matchMap.get(index);
      if (realProfile) {
        // Check if the API response has photos with actual usable URLs
        // WhoLikesMe API may return photo objects with null pictureUrls (blurred/hidden)
        const apiHasPhotoUrls = likeProfile.photos?.some(
          (p: any) => p.pictureUrls?.medium || p.pictureUrls?.large
        );
        const freshPhotos = apiHasPhotoUrls ? likeProfile.photos : realProfile.photos;

        return {
          ...realProfile,
          photos: freshPhotos,
          _originalId: likeProfile.id,
          _matched: true,
          _apiHasPhotos: apiHasPhotoUrls,
        };
      }

      // Pass 2: discovery-matched profiles (no photos, need refresh)
      const discoveredProfile = discoveryMatchMap.get(index);
      if (discoveredProfile) {
        return {
          ...discoveredProfile,
          photos: likeProfile.photos, // Use whatever WhoLikesMe returned (likely null URLs)
          _originalId: likeProfile.id,
          _matched: true,
          _matchedFromDiscovery: true,
          _needsRefresh: true,
          _apiHasPhotos: false,
        };
      }

      return likeProfile;
    });
  }, [allLikes, whoLikedYouProfiles, discoveredProfiles]);

  // Update backend cache with fresh photo URLs (side effect, separate from render)
  const lastCacheUpdateRef = useRef<string>('');
  useEffect(() => {
    const profilesWithFreshPhotos = enrichedLikes.filter((p: any) => p._apiHasPhotos && p._matched);
    if (profilesWithFreshPhotos.length === 0) return;

    // Deduplicate: only update if the set of profiles changed
    const cacheKey = profilesWithFreshPhotos.map((p: any) => p.id).sort().join(',');
    if (cacheKey === lastCacheUpdateRef.current) return;
    lastCacheUpdateRef.current = cacheKey;

    profilesWithFreshPhotos.forEach((profile: any) => {
      updateCachedPhotos(profile, profile.photos);
    });
  }, [enrichedLikes, updateCachedPhotos]);

  // Refresh a single profile to get fresh image URLs
  // For discovery-matched profiles (verifyLiked=true), only saves to whoLikedYou if theirs === 'LIKED'
  // Returns { verified: boolean } so caller can try alternate candidates if needed
  const refreshProfile = useCallback(async (profileId: string, profileName?: string, verifyLiked?: boolean): Promise<{ verified: boolean }> => {
    console.log('Refreshing profile:', profileId, 'name:', profileName, verifyLiked ? '(verifying liked)' : '');

    // If we have a name, try to look up the real ID from whoLikedYouProfiles
    // This handles the case where allLikes has fake IDs
    let realProfileId = profileId;
    if (profileName) {
      const storedProfile = whoLikedYouProfiles.find(
        p => p.imaginaryName?.toLowerCase() === profileName.toLowerCase()
      );
      if (storedProfile) {
        realProfileId = storedProfile.id;
        console.log('Found real ID by name:', realProfileId);
      }
    }

    setRefreshingProfiles(prev => new Set(prev).add(profileId));

    try {
      const result = await apolloClient.query({
        query: PROFILE_QUERY,
        variables: { profileId: realProfileId },
        fetchPolicy: 'network-only', // Force fresh fetch
      });

      const freshProfile = result.data?.profile;
      if (!freshProfile) {
        console.error('Profile not found:', realProfileId);
        return { verified: false };
      }

      console.log('Got fresh profile:', freshProfile.imaginaryName, 'photos:', freshProfile.photos?.length,
        'theirs:', freshProfile.interactionStatus?.theirs);

      // For discovery-matched profiles, verify they actually liked us before saving
      if (verifyLiked && freshProfile.interactionStatus?.theirs !== 'LIKED') {
        console.log('Profile did NOT like us, skipping save:', freshProfile.imaginaryName, realProfileId);
        return { verified: false };
      }

      // Update whoLikedYouProfiles state - search by name since IDs can be fake/real mismatch
      setWhoLikedYouProfiles(prev => {
        const existingIndex = prev.findIndex(
          p => p.imaginaryName?.toLowerCase() === freshProfile.imaginaryName?.toLowerCase()
        );

        if (existingIndex >= 0) {
          // Update existing profile with fresh data
          console.log('Updating existing profile in state:', freshProfile.imaginaryName);
          return prev.map((p, i) => i === existingIndex ? {
            ...p,
            id: freshProfile.id, // Update to real ID
            photos: freshProfile.photos,
            bio: freshProfile.bio,
            desires: freshProfile.desires,
            connectionGoals: freshProfile.connectionGoals,
            verificationStatus: freshProfile.verificationStatus,
            distance: freshProfile.distance,
          } : p);
        } else {
          // Add as new profile
          console.log('Adding new profile to state:', freshProfile.imaginaryName);
          const sf = (v: any) => typeof v === 'string' ? v : '';
          const profileData: WhoLikedYouProfile = {
            id: freshProfile.id,
            imaginaryName: freshProfile.imaginaryName,
            age: freshProfile.age,
            gender: sf(freshProfile.gender),
            sexuality: sf(freshProfile.sexuality),
            bio: freshProfile.bio,
            desires: freshProfile.desires,
            connectionGoals: freshProfile.connectionGoals,
            verificationStatus: freshProfile.verificationStatus,
            distance: freshProfile.distance,
            photos: freshProfile.photos,
            discoveredAt: new Date().toISOString(),
          };
          return [profileData, ...prev];
        }
      });

      // Also update backend storage (sanitize fields that may be objects from GraphQL)
      const safeStr = (v: any) => typeof v === 'string' ? v : '';
      const profileData: WhoLikedYouProfile = {
        id: freshProfile.id,
        imaginaryName: freshProfile.imaginaryName,
        age: freshProfile.age,
        gender: safeStr(freshProfile.gender),
        sexuality: safeStr(freshProfile.sexuality),
        bio: freshProfile.bio,
        desires: freshProfile.desires,
        connectionGoals: freshProfile.connectionGoals,
        verificationStatus: freshProfile.verificationStatus,
        distance: freshProfile.distance,
        photos: freshProfile.photos,
        discoveredAt: new Date().toISOString(),
      };

      const response = await fetch('/api/who-liked-you', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ profile: profileData }),
      });
      const saveResult = await response.json();
      console.log('Saved to backend:', saveResult, 'photos:', profileData.photos?.[0]?.pictureUrls?.medium);

      return { verified: true };
    } catch (e) {
      console.error('Failed to refresh profile:', profileId, e);
      return { verified: false };
    } finally {
      setRefreshingProfiles(prev => {
        const next = new Set(prev);
        next.delete(profileId);
        return next;
      });
    }
  }, [whoLikedYouProfiles]);

  // Refetch all data to get fresh signed image URLs
  const refreshData = useCallback(() => {
    fetchAllLikes();
    fetchAllPings();
  }, [fetchAllLikes, fetchAllPings]);

  // Auto-refresh all matched profiles on page load to get fresh signed photo URLs
  // Cached photos expire after a few hours, so we always refresh on mount
  // Prioritize _needsRefresh (discovery-matched, no photos) before regular refreshes
  // Use ref + sessionStorage to prevent re-triggering if component remounts due to errors
  const autoRefreshStartedRef = useRef(false);
  useEffect(() => {
    if (autoRefreshStartedRef.current || likesLoading || !enrichedLikes.length) return;

    // Check sessionStorage to prevent loops across remounts
    const lastRefresh = sessionStorage.getItem('likes_auto_refresh_ts');
    if (lastRefresh && Date.now() - parseInt(lastRefresh) < 60000) return; // Skip if refreshed within last minute

    const matchedProfiles = enrichedLikes.filter((p: any) => p._matched && p.id);
    if (matchedProfiles.length === 0) return;

    autoRefreshStartedRef.current = true;
    sessionStorage.setItem('likes_auto_refresh_ts', String(Date.now()));

    // Prioritize: discovery-matched (no photos) first, then regular refreshes
    const needsRefresh = matchedProfiles.filter((p: any) => p._needsRefresh);
    const regularRefresh = matchedProfiles.filter((p: any) => !p._needsRefresh);
    const orderedProfiles = [...needsRefresh, ...regularRefresh];

    console.log(`Auto-refreshing ${orderedProfiles.length} matched profiles (${needsRefresh.length} discovery-matched, ${regularRefresh.length} regular)`);

    const refreshSequentially = async () => {
      for (const profile of orderedProfiles) {
        try {
          if (profile._matchedFromDiscovery) {
            // Discovery match: verify each candidate via ProfileQuery
            const candidateIds: string[] = profile._allCandidateIds || [profile.id];
            let verified = false;
            for (const candidateId of candidateIds) {
              console.log(`Verifying candidate ${candidateId} for "${profile.imaginaryName}"`);
              const result = await refreshProfile(candidateId, profile.imaginaryName, true);
              if (result.verified) {
                console.log(`Verified! ${candidateId} liked us as "${profile.imaginaryName}"`);
                verified = true;
                break;
              }
              await new Promise(resolve => setTimeout(resolve, 200));
            }
            if (!verified) {
              console.log(`No candidates verified for "${profile.imaginaryName}" (${candidateIds.length} tried)`);
            }
          } else {
            // Regular Pass 1 match: just refresh for fresh photos
            await refreshProfile(profile.id, profile.imaginaryName);
          }
        } catch (e) {
          console.error('Auto-refresh failed for:', profile.imaginaryName, e);
        }
        await new Promise(resolve => setTimeout(resolve, 200));
      }
    };

    refreshSequentially();
  }, [likesLoading, enrichedLikes]);

  // Handle disliking a profile from the Likes page
  const handleDislikeFromLikes = useCallback(async (profile: any) => {
    // Only allow dislike if profile was matched with real scanner data
    if (!profile._matched) {
      console.log('Cannot dislike profile without real data:', profile.imaginaryName);
      return { success: false, error: 'No real profile data' };
    }

    const profileId = profile.id;

    setDislikingProfiles(prev => new Set(prev).add(profileId));

    try {
      const safeStr = (v: any) => typeof v === 'string' ? v : '';
      const result = await dislikeProfile({
        id: profileId,
        imaginaryName: profile.imaginaryName,
        age: profile.age,
        gender: safeStr(profile.gender),
        sexuality: safeStr(profile.sexuality),
        photos: profile.photos,
      });

      if (result.success) {
        console.log('Disliked from Likes page:', profile.imaginaryName);
        // Remove from whoLikedYouProfiles
        setWhoLikedYouProfiles(prev => prev.filter(p => p.id !== profileId));
        // Refresh likes list
        fetchAllLikes();
      }

      return result;
    } finally {
      setDislikingProfiles(prev => {
        const next = new Set(prev);
        next.delete(profileId);
        return next;
      });
    }
  }, [dislikeProfile, fetchAllLikes]);

  // Fetch past likes (You Liked tab).
  // Feeld's pastLikes API returns synthetic (v5) profile IDs that don't resolve
  // via ProfileQuery — deliberate anonymization for non-Majestic viewers.
  // We sidestep this by using the REAL profile IDs we stored locally at like-time
  // (`liked_profiles` in localStorage / backend) and fetching each via ProfileQuery
  // directly. This returns full profile data + real photo URLs.
  const fetchPastLikes = useCallback(async (_cursor?: string | null) => {
    setPastLikesLoading(true);
    try {
      const localLikes = await dataSync.getLikedProfiles();

      const enriched = await Promise.all(
        localLikes.map(async (l) => {
          try {
            const r = await apolloClient.query({
              query: PROFILE_QUERY,
              variables: { profileId: l.id },
              fetchPolicy: 'network-only',
            });
            const profile = r.data?.profile;
            if (profile) {
              return {
                profile,
                isPing: false,
                interactionSentAt: new Date(l.likedAt).toISOString(),
              };
            }
          } catch (e) {
            console.warn(`ProfileQuery failed for ${l.id} (${l.name}):`, e);
          }
          return {
            profile: { id: l.id, imaginaryName: l.name, photos: [] },
            isPing: false,
            interactionSentAt: new Date(l.likedAt).toISOString(),
            _profileFetchFailed: true,
          };
        })
      );

      enriched.sort(
        (a, b) =>
          new Date(b.interactionSentAt).getTime() -
          new Date(a.interactionSentAt).getTime()
      );

      setPastLikes(enriched);
      setPastLikesTotal(enriched.length);
      setPastLikesCursor(null);
      setPastLikesHasMore(false);
      console.log(`Loaded ${enriched.length} past likes from local IDs`);
    } catch (e) {
      console.error('Failed to load past likes from local:', e);
    } finally {
      setPastLikesLoading(false);
    }
  }, []);

  // Fetch past dislikes from API (Passed tab)
  const fetchPastDislikes = useCallback(async (cursor?: string | null) => {
    setPastDislikesLoading(true);
    try {
      const result = await apolloClient.query({
        query: PAST_DISLIKES_QUERY,
        variables: {
          input: { sortDirection: 'NEWEST_FIRST' },
          limit: 25,
          ...(cursor ? { cursor } : {}),
        },
        fetchPolicy: 'network-only',
      });

      const nodes = result.data?.pastDislikes?.nodes || [];
      const pageInfo = result.data?.pastDislikes?.pageInfo;

      if (cursor) {
        setPastDislikes(prev => [...prev, ...nodes]);
      } else {
        setPastDislikes(nodes);
      }
      setPastDislikesTotal(pageInfo?.total || 0);
      setPastDislikesCursor(pageInfo?.nextPageCursor || null);
      setPastDislikesHasMore(pageInfo?.hasNextPage || false);
      console.log(`Fetched ${nodes.length} past dislikes, total: ${pageInfo?.total}, hasMore: ${pageInfo?.hasNextPage}`);
    } catch (e) {
      console.error('Failed to fetch past dislikes:', e);
    } finally {
      setPastDislikesLoading(false);
    }
  }, []);

  // Undo last dislike
  const handleUndoDislike = useCallback(async () => {
    setUndoLoading(true);
    setUndoError(null);
    try {
      await apolloClient.mutate({
        mutation: UNDO_PROFILE_DISLIKE_MUTATION,
      });
      console.log('Undo dislike successful');
      // Refetch to show updated list
      fetchPastDislikes();
    } catch (e: any) {
      const msg = e?.graphQLErrors?.[0]?.message || e?.message || 'Unknown error';
      if (msg.toLowerCase().includes('majestic') || msg.toLowerCase().includes('not majestic')) {
        setUndoError('Account is not majestic');
      } else {
        setUndoError(msg);
      }
      console.error('Undo dislike failed:', e);
    } finally {
      setUndoLoading(false);
    }
  }, [fetchPastDislikes]);

  // Handle accept ping
  const handleAcceptPing = useCallback(async (profileId: string) => {
    setPingActionLoading(prev => new Set(prev).add(profileId));
    try {
      const result = await apolloClient.mutate({
        mutation: PROFILE_ACCEPT_PING_MUTATION,
        variables: { targetProfileId: profileId },
      });
      console.log('Accept ping result:', result.data);
      // Show matched indicator briefly
      setPingMatched(prev => new Set(prev).add(profileId));
      setTimeout(() => {
        setPingMatched(prev => {
          const next = new Set(prev);
          next.delete(profileId);
          return next;
        });
        // Remove from pings list
        setAllPings(prev => prev.filter(p => p.id !== profileId));
        setPingsTotal(prev => Math.max(0, prev - 1));
      }, 1500);
    } catch (e) {
      console.error('Failed to accept ping:', e);
    } finally {
      setPingActionLoading(prev => {
        const next = new Set(prev);
        next.delete(profileId);
        return next;
      });
    }
  }, []);

  // Handle reject ping
  const handleRejectPing = useCallback(async (profileId: string) => {
    setPingActionLoading(prev => new Set(prev).add(profileId));
    try {
      await apolloClient.mutate({
        mutation: PROFILE_REJECT_PING_MUTATION,
        variables: { targetProfileId: profileId },
      });
      console.log('Rejected ping from:', profileId);
      // Remove from pings list
      setAllPings(prev => prev.filter(p => p.id !== profileId));
      setPingsTotal(prev => Math.max(0, prev - 1));
    } catch (e) {
      console.error('Failed to reject ping:', e);
    } finally {
      setPingActionLoading(prev => {
        const next = new Set(prev);
        next.delete(profileId);
        return next;
      });
    }
  }, []);

  // Prefetch past likes + dislikes on mount so tab badges show accurate counts
  // before the user clicks into either tab.
  useEffect(() => {
    fetchPastLikes();
    fetchPastDislikes();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Refetch when user switches to the tab (keeps data fresh on revisit)
  useEffect(() => {
    if (activeTab === 'youLiked') {
      fetchPastLikes();
    } else if (activeTab === 'disliked') {
      fetchPastDislikes();
    }
  }, [activeTab, fetchPastLikes, fetchPastDislikes]);

  // Scanner-cache index by profile ID — used to enrich pastLikes with real photos
  // when Feeld gates them. Must be declared before any early return.
  const discoveredById = useMemo(() => {
    const map = new Map<string, any>();
    for (const p of discoveredProfiles) {
      if (p?.id) map.set(p.id, p);
    }
    return map;
  }, [discoveredProfiles]);

  const loading = likesLoading || pingsLoading;

  if (loading && activeTab !== 'youLiked' && activeTab !== 'disliked' && activeTab !== 'saved') return <LoadingPage message="Loading interactions..." />;

  const likes = enrichedLikes;
  const pings = allPings;

  // Count how many likes have been matched with real data
  const matchedCount = enrichedLikes.filter((p: any) => p._matched).length;

  // Each node.profile already has fresh data from ProfileQuery using the real local ID.
  // Scanner cache is used only as a last-resort fallback if the fetch failed.
  const pastLikesProfiles = pastLikes.map((node: any) => {
    const fresh = node.profile || {};
    const cached = node._profileFetchFailed ? discoveredById.get(fresh.id) : null;
    return {
      ...(cached || {}),
      ...fresh,
      photos: fresh.photos?.length ? fresh.photos : (cached?.photos || []),
      _isPing: node.isPing,
      _interactionSentAt: node.interactionSentAt,
      _profileFetchFailed: node._profileFetchFailed,
    };
  });

  // Map pastDislikes nodes to profiles for the grid
  const pastDislikesProfiles = pastDislikes.map((node: any) => ({
    ...node.profile,
    _interactionSentAt: node.interactionSentAt,
  }));

  const currentProfiles =
    activeTab === 'likes' ? likes :
    activeTab === 'pings' ? pings :
    activeTab === 'disliked' ? pastDislikesProfiles :
    activeTab === 'saved' ? savedProfiles :
    pastLikesProfiles;

  return (
    <div style={styles.container}>
      {/* Header */}
      <div style={styles.header}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
          <h1 style={styles.title}>Interactions</h1>
          <button
            onClick={refreshData}
            disabled={likesLoading || pingsLoading}
            style={{
              display: 'flex',
              alignItems: 'center',
              gap: '6px',
              padding: '8px 14px',
              borderRadius: '8px',
              border: '1px solid rgba(255,255,255,0.1)',
              background: 'rgba(255,255,255,0.05)',
              color: 'rgba(255,255,255,0.7)',
              fontSize: '13px',
              fontWeight: 500,
              fontFamily: "'Satoshi', sans-serif",
              cursor: (likesLoading || pingsLoading) ? 'not-allowed' : 'pointer',
              opacity: (likesLoading || pingsLoading) ? 0.5 : 1,
              transition: 'all 0.2s ease',
            }}
            title="Refresh to get new image URLs (they expire after a few hours)"
          >
            <svg
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              strokeWidth="2"
              style={{
                width: '14px',
                height: '14px',
                animation: (likesLoading || pingsLoading) ? 'spin 1s linear infinite' : 'none',
              }}
            >
              <path strokeLinecap="round" strokeLinejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
            </svg>
            Refresh
          </button>
        </div>
        <p style={styles.subtitle}>People who've shown interest in you</p>
      </div>

      {/* Tabs */}
      <div style={styles.tabContainer}>
        <button
          onClick={() => setActiveTab('likes')}
          style={styles.tab(activeTab === 'likes', 'likes')}
        >
          <svg viewBox="0 0 24 24" fill="currentColor" style={{ width: '18px', height: '18px' }}>
            <path d="M11.645 20.91l-.007-.003-.022-.012a15.247 15.247 0 01-.383-.218 25.18 25.18 0 01-4.244-3.17C4.688 15.36 2.25 12.174 2.25 8.25 2.25 5.322 4.714 3 7.688 3A5.5 5.5 0 0112 5.052 5.5 5.5 0 0116.313 3c2.973 0 5.437 2.322 5.437 5.25 0 3.925-2.438 7.111-4.739 9.256a25.175 25.175 0 01-4.244 3.17 15.247 15.247 0 01-.383.219l-.022.012-.007.004-.003.001a.752.752 0 01-.704 0l-.003-.001z" />
          </svg>
          Likes
          <span style={styles.tabBadge(activeTab === 'likes', 'likes')}>
            {likesTotal}
          </span>
        </button>

        <button
          onClick={() => setActiveTab('pings')}
          style={styles.tab(activeTab === 'pings', 'pings')}
        >
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" style={{ width: '18px', height: '18px' }}>
            <path strokeLinecap="round" strokeLinejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0" />
          </svg>
          Pings
          <span style={styles.tabBadge(activeTab === 'pings', 'pings')}>
            {pingsTotal}
          </span>
        </button>

        <button
          onClick={() => setActiveTab('youLiked')}
          style={styles.tab(activeTab === 'youLiked', 'youLiked')}
        >
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" style={{ width: '18px', height: '18px' }}>
            <path strokeLinecap="round" strokeLinejoin="round" d="M6 12L3.269 3.126A59.768 59.768 0 0121.485 12 59.77 59.77 0 013.27 20.876L5.999 12zm0 0h7.5" />
          </svg>
          You Liked
          <span style={styles.tabBadge(activeTab === 'youLiked', 'youLiked')}>
            {pastLikesTotal || pastLikesProfiles.length}
          </span>
        </button>

        <button
          onClick={() => setActiveTab('disliked')}
          style={styles.tab(activeTab === 'disliked', 'disliked')}
        >
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" style={{ width: '18px', height: '18px' }}>
            <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
          </svg>
          Passed
          <span style={styles.tabBadge(activeTab === 'disliked', 'disliked')}>
            {pastDislikesTotal || pastDislikesProfiles.length}
          </span>
        </button>

        <button
          onClick={() => setActiveTab('saved')}
          style={styles.tab(activeTab === 'saved', 'saved')}
        >
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ width: '18px', height: '18px' }}>
            <path d="M17.593 3.322c1.1.128 1.907 1.077 1.907 2.185V21L12 17.25 4.5 21V5.507c0-1.108.806-2.057 1.907-2.185a48.507 48.507 0 0111.186 0z" />
          </svg>
          Saved
          <span style={styles.tabBadge(activeTab === 'saved', 'saved')}>
            {favorites.length}
          </span>
        </button>
      </div>

      {/* Location Scanner */}
      {activeTab === 'likes' && (
        <div style={styles.scannerContainer}>
          <select
            value={selectedLocationId}
            onChange={(e) => setSelectedLocationId(e.target.value)}
            style={styles.locationSelect}
            disabled={isScanning}
          >
            <option value="">Select a location to scan...</option>
            {savedLocations.map(loc => (
              <option key={loc.id} value={loc.id}>
                {loc.name}
              </option>
            ))}
          </select>
          <button
            onClick={scanForLikes}
            style={styles.scanButton(isScanning)}
            disabled={isScanning || !selectedLocationId}
          >
            {isScanning ? (
              <>
                <svg
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  strokeWidth="2"
                  style={{ width: '16px', height: '16px', animation: 'spin 1s linear infinite' }}
                >
                  <path strokeLinecap="round" strokeLinejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
                </svg>
                Scanning...
              </>
            ) : (
              <>
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" style={{ width: '16px', height: '16px' }}>
                  <path strokeLinecap="round" strokeLinejoin="round" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
                </svg>
                Scan for Likes
              </>
            )}
          </button>
          {matchedCount > 0 && (
            <span style={styles.foundBadge}>
              <svg viewBox="0 0 24 24" fill="currentColor" style={{ width: '12px', height: '12px' }}>
                <path fillRule="evenodd" d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zm13.36-1.814a.75.75 0 10-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 00-1.06 1.06l2.25 2.25a.75.75 0 001.14-.094l3.75-5.25z" clipRule="evenodd" />
              </svg>
              {matchedCount} identified
            </span>
          )}
          <button
            onClick={isFuckItScanning ? cancelScan : scanAllLocations}
            disabled={isScanning || (!isFuckItScanning && savedLocations.length === 0)}
            style={{
              display: 'flex',
              alignItems: 'center',
              gap: '8px',
              padding: '12px 20px',
              borderRadius: '8px',
              border: 'none',
              background: isFuckItScanning
                ? 'rgba(239,68,68,0.2)'
                : 'linear-gradient(135deg, #ef4444 0%, #dc2626 100%)',
              color: '#fff',
              fontSize: '14px',
              fontWeight: 600,
              fontFamily: "'Satoshi', sans-serif",
              cursor: (isScanning || isFuckItScanning) ? 'not-allowed' : 'pointer',
              opacity: (isScanning || isFuckItScanning) ? 0.7 : 1,
              transition: 'all 0.2s ease',
              whiteSpace: 'nowrap' as const,
              marginLeft: 'auto',
            }}
          >
            {isFuckItScanning ? (
              <span onClick={(e) => { e.stopPropagation(); cancelScan(); }} style={{ cursor: 'pointer', display: 'flex', alignItems: 'center', gap: '8px' }}>
                <svg
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  strokeWidth="2"
                  style={{ width: '16px', height: '16px' }}
                >
                  <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
                </svg>
                {fuckItProgress.currentLocation} ({fuckItProgress.current}/{fuckItProgress.total}) • {fuckItProgress.totalProfiles} profiles • {fuckItProgress.totalMatches} matches — tap to cancel
              </span>
            ) : (
              <>
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" style={{ width: '16px', height: '16px' }}>
                  <path strokeLinecap="round" strokeLinejoin="round" d="M15.362 5.214A8.252 8.252 0 0112 21 8.25 8.25 0 016.038 7.048 8.287 8.287 0 009 9.6a8.983 8.983 0 013.361-6.867 8.21 8.21 0 003 2.48z" />
                  <path strokeLinecap="round" strokeLinejoin="round" d="M12 18a3.75 3.75 0 00.495-7.467 5.99 5.99 0 00-1.925 3.546 5.974 5.974 0 01-2.133-1A3.75 3.75 0 0012 18z" />
                </svg>
                Fuck It ({savedLocations.length} cities)
              </>
            )}
          </button>
        </div>
      )}

      {/* Scan Status */}
      {scanStatus && activeTab === 'likes' && (
        <div style={styles.scanStatus}>{scanStatus}</div>
      )}

      {/* Loading state for You Liked */}
      {activeTab === 'youLiked' && pastLikesLoading && pastLikes.length === 0 && (
        <div style={styles.profileGrid}>
          <LoadingCards count={6} />
        </div>
      )}

      {/* Loading state for Passed */}
      {activeTab === 'disliked' && pastDislikesLoading && pastDislikes.length === 0 && (
        <div style={styles.profileGrid}>
          <LoadingCards count={6} />
        </div>
      )}

      {/* Undo Last Pass button for Passed tab */}
      {activeTab === 'disliked' && pastDislikesProfiles.length > 0 && (
        <div style={{ marginBottom: '16px' }}>
          <button
            onClick={handleUndoDislike}
            disabled={undoLoading}
            style={{
              display: 'flex',
              alignItems: 'center',
              gap: '8px',
              padding: '10px 18px',
              borderRadius: '10px',
              border: '1px solid rgba(100,116,139,0.3)',
              background: undoLoading ? 'rgba(100,116,139,0.1)' : 'rgba(100,116,139,0.15)',
              color: undoLoading ? 'rgba(255,255,255,0.4)' : 'rgba(255,255,255,0.8)',
              fontSize: '13px',
              fontWeight: 600,
              fontFamily: "'Satoshi', sans-serif",
              cursor: undoLoading ? 'not-allowed' : 'pointer',
              transition: 'all 0.2s ease',
            }}
          >
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" style={{ width: '16px', height: '16px' }}>
              <path strokeLinecap="round" strokeLinejoin="round" d="M9 15L3 9m0 0l6-6M3 9h12a6 6 0 010 12h-3" />
            </svg>
            {undoLoading ? 'Undoing...' : 'Undo Last Pass'}
          </button>
          {undoError && (
            <div style={{
              marginTop: '8px',
              padding: '8px 14px',
              borderRadius: '8px',
              background: 'rgba(245,158,11,0.15)',
              border: '1px solid rgba(245,158,11,0.3)',
              color: '#fcd34d',
              fontSize: '13px',
              fontFamily: "'Satoshi', sans-serif",
            }}>
              {undoError}
            </div>
          )}
        </div>
      )}

      {/* Empty State */}
      {currentProfiles.length === 0 && !(activeTab === 'youLiked' && pastLikesLoading && pastLikes.length === 0) && !(activeTab === 'disliked' && pastDislikesLoading && pastDislikes.length === 0) ? (
        <div style={styles.emptyState}>
          <div style={styles.emptyIcon(activeTab)}>
            {activeTab === 'likes' ? (
              <svg viewBox="0 0 24 24" fill="none" stroke="#be3144" strokeWidth="1" style={{ width: '40px', height: '40px' }}>
                <path strokeLinecap="round" strokeLinejoin="round" d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12z" />
              </svg>
            ) : activeTab === 'pings' ? (
              <svg viewBox="0 0 24 24" fill="none" stroke="#f59e0b" strokeWidth="1" style={{ width: '40px', height: '40px' }}>
                <path strokeLinecap="round" strokeLinejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0" />
              </svg>
            ) : activeTab === 'disliked' ? (
              <svg viewBox="0 0 24 24" fill="none" stroke="#64748b" strokeWidth="1" style={{ width: '40px', height: '40px' }}>
                <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
              </svg>
            ) : activeTab === 'saved' ? (
              <svg viewBox="0 0 24 24" fill="none" stroke="#a855f7" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" style={{ width: '40px', height: '40px' }}>
                <path d="M17.593 3.322c1.1.128 1.907 1.077 1.907 2.185V21L12 17.25 4.5 21V5.507c0-1.108.806-2.057 1.907-2.185a48.507 48.507 0 0111.186 0z" />
              </svg>
            ) : (
              <svg viewBox="0 0 24 24" fill="none" stroke="#22c55e" strokeWidth="1" style={{ width: '40px', height: '40px' }}>
                <path strokeLinecap="round" strokeLinejoin="round" d="M6 12L3.269 3.126A59.768 59.768 0 0121.485 12 59.77 59.77 0 013.27 20.876L5.999 12zm0 0h7.5" />
              </svg>
            )}
          </div>
          <h2 style={styles.emptyTitle}>
            {activeTab === 'youLiked' ? 'No likes sent yet'
              : activeTab === 'disliked' ? 'No passes yet'
              : activeTab === 'saved' ? 'Nothing saved yet'
              : `No ${activeTab} yet`}
          </h2>
          <p style={styles.emptyText}>
            {activeTab === 'likes'
              ? "When someone likes you, they'll appear here"
              : activeTab === 'pings'
              ? 'Pings from interested members will show up here'
              : activeTab === 'disliked'
              ? "Profiles you've passed on will appear here"
              : activeTab === 'saved'
              ? 'Tap the star on a Discover card to save profiles for later'
              : "Profiles you've liked will appear here"
            }
          </p>
        </div>
      ) : !(activeTab === 'youLiked' && pastLikesLoading && pastLikes.length === 0) && !(activeTab === 'disliked' && pastDislikesLoading && pastDislikes.length === 0) && (
        <>
          {/* Profiles Grid */}
          <div style={styles.profileGrid}>
            {currentProfiles.map((profile: any, index: number) => {
              // Only show dislike for profiles that have been matched with real scanner data
              const canDislike = activeTab === 'likes' && profile._matched && !isDisliked(profile.id);

              return (
                <div key={profile.id || index} style={{ position: 'relative' }}>
                  {/* Ping badge for You Liked tab */}
                  {activeTab === 'youLiked' && profile._isPing && (
                    <div style={{
                      position: 'absolute',
                      top: '8px',
                      left: '8px',
                      zIndex: 10,
                      display: 'flex',
                      alignItems: 'center',
                      gap: '4px',
                      padding: '3px 8px',
                      borderRadius: '6px',
                      background: 'rgba(245,158,11,0.85)',
                      color: '#fff',
                      fontSize: '11px',
                      fontWeight: 700,
                      fontFamily: "'Satoshi', sans-serif",
                      backdropFilter: 'blur(4px)',
                    }}>
                      <svg viewBox="0 0 24 24" fill="currentColor" style={{ width: '10px', height: '10px' }}>
                        <path d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0" />
                      </svg>
                      Ping
                    </div>
                  )}

                  {/* Reciprocation status for You Liked tab */}
                  {activeTab === 'youLiked' && (() => {
                    const theirs = profile.interactionStatus?.theirs;
                    if (theirs !== 'LIKED' && theirs !== 'DISLIKED') return null;
                    const isMatch = theirs === 'LIKED';
                    return (
                      <div style={{
                        position: 'absolute',
                        bottom: '8px',
                        left: '8px',
                        zIndex: 10,
                        display: 'flex',
                        alignItems: 'center',
                        gap: '4px',
                        padding: '4px 9px',
                        borderRadius: '6px',
                        background: isMatch ? 'rgba(34,197,94,0.85)' : 'rgba(100,116,139,0.85)',
                        color: '#fff',
                        fontSize: '11px',
                        fontWeight: 700,
                        fontFamily: "'Satoshi', sans-serif",
                        backdropFilter: 'blur(4px)',
                        letterSpacing: '0.02em',
                      }}>
                        {isMatch ? 'Liked back' : 'Passed'}
                      </div>
                    );
                  })()}

                  {/* Timestamp badge for You Liked and Passed tabs */}
                  {(activeTab === 'youLiked' || activeTab === 'disliked') && profile._interactionSentAt && (
                    <div style={{
                      position: 'absolute',
                      top: '8px',
                      right: '8px',
                      zIndex: 10,
                      padding: '3px 8px',
                      borderRadius: '6px',
                      background: 'rgba(0,0,0,0.65)',
                      color: 'rgba(255,255,255,0.8)',
                      fontSize: '10px',
                      fontWeight: 600,
                      fontFamily: "'Satoshi', sans-serif",
                      backdropFilter: 'blur(4px)',
                    }}>
                      {new Date(profile._interactionSentAt).toLocaleDateString(undefined, { month: 'short', day: 'numeric' })}
                    </div>
                  )}

                  {/* Matched indicator for accepted pings */}
                  {activeTab === 'pings' && pingMatched.has(profile.id) && (
                    <div style={{
                      position: 'absolute',
                      inset: 0,
                      zIndex: 20,
                      display: 'flex',
                      alignItems: 'center',
                      justifyContent: 'center',
                      background: 'rgba(34,197,94,0.85)',
                      borderRadius: '12px',
                      backdropFilter: 'blur(4px)',
                    }}>
                      <span style={{
                        color: '#fff',
                        fontSize: '24px',
                        fontWeight: 700,
                        fontFamily: "'Clash Display', sans-serif",
                      }}>Matched!</span>
                    </div>
                  )}

                  <ProfileCard
                    profile={profile}
                    onClick={() => setSelectedProfileId(profile.id)}
                    index={index}
                    onRefresh={activeTab === 'likes' ? (id) => refreshProfile(id, profile.imaginaryName) : undefined}
                    isRefreshing={refreshingProfiles.has(profile.id)}
                    onDislike={canDislike ? handleDislikeFromLikes : undefined}
                    isDisliking={dislikingProfiles.has(profile.id)}
                    showDislike={canDislike}
                  />

                  {/* Accept/Reject buttons for Pings tab */}
                  {activeTab === 'pings' && !pingMatched.has(profile.id) && (
                    <div style={{
                      display: 'flex',
                      gap: '8px',
                      marginTop: '8px',
                    }}>
                      <button
                        onClick={(e) => { e.stopPropagation(); handleRejectPing(profile.id); }}
                        disabled={pingActionLoading.has(profile.id)}
                        style={{
                          flex: 1,
                          display: 'flex',
                          alignItems: 'center',
                          justifyContent: 'center',
                          gap: '6px',
                          padding: '10px',
                          borderRadius: '10px',
                          border: '1px solid rgba(239,68,68,0.3)',
                          background: 'rgba(239,68,68,0.15)',
                          color: '#fca5a5',
                          fontSize: '13px',
                          fontWeight: 600,
                          fontFamily: "'Satoshi', sans-serif",
                          cursor: pingActionLoading.has(profile.id) ? 'not-allowed' : 'pointer',
                          opacity: pingActionLoading.has(profile.id) ? 0.5 : 1,
                          transition: 'all 0.2s ease',
                        }}
                      >
                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" style={{ width: '16px', height: '16px' }}>
                          <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
                        </svg>
                        {pingActionLoading.has(profile.id) ? '...' : 'Reject'}
                      </button>
                      <button
                        onClick={(e) => { e.stopPropagation(); handleAcceptPing(profile.id); }}
                        disabled={pingActionLoading.has(profile.id)}
                        style={{
                          flex: 1,
                          display: 'flex',
                          alignItems: 'center',
                          justifyContent: 'center',
                          gap: '6px',
                          padding: '10px',
                          borderRadius: '10px',
                          border: 'none',
                          background: pingActionLoading.has(profile.id) ? 'rgba(34,197,94,0.2)' : 'linear-gradient(135deg, #22c55e 0%, #16a34a 100%)',
                          color: '#fff',
                          fontSize: '13px',
                          fontWeight: 600,
                          fontFamily: "'Satoshi', sans-serif",
                          cursor: pingActionLoading.has(profile.id) ? 'not-allowed' : 'pointer',
                          opacity: pingActionLoading.has(profile.id) ? 0.5 : 1,
                          transition: 'all 0.2s ease',
                        }}
                      >
                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" style={{ width: '16px', height: '16px' }}>
                          <path strokeLinecap="round" strokeLinejoin="round" d="M4.5 12.75l6 6 9-13.5" />
                        </svg>
                        {pingActionLoading.has(profile.id) ? '...' : 'Accept'}
                      </button>
                    </div>
                  )}
                </div>
              );
            })}
          </div>

          {/* Load More button for You Liked tab */}
          {activeTab === 'youLiked' && pastLikesHasMore && (
            <div style={{ display: 'flex', justifyContent: 'center', marginTop: '24px' }}>
              <button
                onClick={() => fetchPastLikes(pastLikesCursor)}
                disabled={pastLikesLoading}
                style={{
                  display: 'flex',
                  alignItems: 'center',
                  gap: '8px',
                  padding: '12px 28px',
                  borderRadius: '10px',
                  border: '1px solid rgba(34,197,94,0.3)',
                  background: pastLikesLoading ? 'rgba(34,197,94,0.1)' : 'rgba(34,197,94,0.15)',
                  color: pastLikesLoading ? 'rgba(255,255,255,0.4)' : '#86efac',
                  fontSize: '14px',
                  fontWeight: 600,
                  fontFamily: "'Satoshi', sans-serif",
                  cursor: pastLikesLoading ? 'not-allowed' : 'pointer',
                  transition: 'all 0.2s ease',
                }}
              >
                {pastLikesLoading ? 'Loading...' : `Load More (${pastLikesProfiles.length} of ${pastLikesTotal})`}
              </button>
            </div>
          )}

          {/* Load More button for Passed tab */}
          {activeTab === 'disliked' && pastDislikesHasMore && (
            <div style={{ display: 'flex', justifyContent: 'center', marginTop: '24px' }}>
              <button
                onClick={() => fetchPastDislikes(pastDislikesCursor)}
                disabled={pastDislikesLoading}
                style={{
                  display: 'flex',
                  alignItems: 'center',
                  gap: '8px',
                  padding: '12px 28px',
                  borderRadius: '10px',
                  border: '1px solid rgba(100,116,139,0.3)',
                  background: pastDislikesLoading ? 'rgba(100,116,139,0.1)' : 'rgba(100,116,139,0.15)',
                  color: pastDislikesLoading ? 'rgba(255,255,255,0.4)' : '#94a3b8',
                  fontSize: '14px',
                  fontWeight: 600,
                  fontFamily: "'Satoshi', sans-serif",
                  cursor: pastDislikesLoading ? 'not-allowed' : 'pointer',
                  transition: 'all 0.2s ease',
                }}
              >
                {pastDislikesLoading ? 'Loading...' : `Load More (${pastDislikesProfiles.length} of ${pastDislikesTotal})`}
              </button>
            </div>
          )}
        </>
      )}

      {/* Profile Detail Modal */}
      {selectedProfileId && (
        <ProfileDetailModal
          profileId={selectedProfileId}
          onClose={() => setSelectedProfileId(null)}
          // When acting on a profile from the Saved tab, auto-remove it from
          // favorites. The action itself (Like/Ping/Dislike) is already
          // persisted to its own queue by the modal's mutation handlers.
          onActionTaken={
            activeTab === 'saved' && selectedProfileId
              ? () => { removeFavorite(selectedProfileId); }
              : undefined
          }
        />
      )}
    </div>
  );
}
