import { useState, useCallback, useEffect, useRef, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { useQuery } from '@apollo/client/react';
import { ProfileCard } from '../components/profile/ProfileCard';
import { ProfileDetailModal } from '../components/profile/ProfileDetailModal';
import { useMatches } from '../hooks/useMatches';
import type { MatchFilters, MatchWeights } from '../hooks/useMatches';
import { apolloClient } from '../api/client';
import { PROFILE_QUERY, PROFILE_MATCHES_QUERY, GET_PROFILE_CONNECTIONS_QUERY } from '../api/operations/queries';
import { authManager } from '../api/auth';

const safeText = (v: any): string => {
  if (v == null) return '';
  if (typeof v === 'string') return v;
  if (typeof v === 'number' || typeof v === 'boolean') return String(v);
  return '';
};

const styles = {
  container: {
    paddingBottom: '48px',
  },
  header: {
    marginBottom: '24px',
  },
  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,
  },
  headerActions: {
    display: 'flex',
    gap: '8px',
    marginTop: '12px',
  },
  iconBtn: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    width: '40px',
    height: '40px',
    borderRadius: '10px',
    border: '1px solid rgba(255,255,255,0.1)',
    background: 'rgba(255,255,255,0.03)',
    color: 'rgba(255,255,255,0.7)',
    cursor: 'pointer',
    fontSize: '18px',
    transition: 'all 0.2s',
  },

  // Filter bar
  filterBar: {
    display: 'flex',
    flexWrap: 'wrap' as const,
    gap: '10px',
    marginBottom: '20px',
    alignItems: 'center',
  },
  searchInput: {
    flex: '1 1 200px',
    minWidth: '200px',
    padding: '10px 14px',
    borderRadius: '10px',
    border: '1px solid rgba(255,255,255,0.1)',
    background: 'rgba(255,255,255,0.03)',
    color: '#ffffff',
    fontSize: '14px',
    fontFamily: "'Satoshi', sans-serif",
    outline: 'none',
  },
  numberInput: {
    width: '70px',
    padding: '10px 8px',
    borderRadius: '10px',
    border: '1px solid rgba(255,255,255,0.1)',
    background: 'rgba(255,255,255,0.03)',
    color: '#ffffff',
    fontSize: '14px',
    fontFamily: "'Satoshi', sans-serif",
    outline: 'none',
    textAlign: 'center' as const,
  },
  select: {
    padding: '10px 14px',
    borderRadius: '10px',
    border: '1px solid rgba(255,255,255,0.1)',
    background: 'rgba(255,255,255,0.05)',
    color: '#ffffff',
    fontSize: '14px',
    fontFamily: "'Satoshi', sans-serif",
    outline: 'none',
    cursor: 'pointer',
  },
  toggleBtn: (active: boolean) => ({
    padding: '10px 16px',
    borderRadius: '10px',
    border: active ? '1px solid rgba(168,85,247,0.4)' : '1px solid rgba(255,255,255,0.1)',
    background: active ? 'rgba(168,85,247,0.15)' : 'rgba(255,255,255,0.03)',
    color: active ? '#c084fc' : 'rgba(255,255,255,0.6)',
    fontSize: '13px',
    fontWeight: 600,
    fontFamily: "'Satoshi', sans-serif",
    cursor: 'pointer',
    transition: 'all 0.2s',
    whiteSpace: 'nowrap' as const,
  }),
  clearBtn: {
    padding: '10px 14px',
    borderRadius: '10px',
    border: '1px solid rgba(239,68,68,0.2)',
    background: 'rgba(239,68,68,0.08)',
    color: '#f87171',
    fontSize: '13px',
    fontWeight: 600,
    fontFamily: "'Satoshi', sans-serif",
    cursor: 'pointer',
    whiteSpace: 'nowrap' as const,
  },
  filterLabel: {
    fontSize: '12px',
    color: 'rgba(255,255,255,0.4)',
    fontFamily: "'Satoshi', sans-serif",
    whiteSpace: 'nowrap' as const,
  },

  // Sort bar
  sortBar: {
    display: 'flex',
    gap: '8px',
    marginBottom: '20px',
    alignItems: 'center',
  },
  sortLabel: {
    fontSize: '13px',
    color: 'rgba(255,255,255,0.4)',
    fontFamily: "'Satoshi', sans-serif",
    marginRight: '4px',
  },
  sortBtn: (active: boolean) => ({
    padding: '6px 14px',
    borderRadius: '8px',
    border: 'none',
    background: active ? 'rgba(255,255,255,0.1)' : 'transparent',
    color: active ? '#ffffff' : 'rgba(255,255,255,0.5)',
    fontSize: '13px',
    fontWeight: active ? 600 : 400,
    fontFamily: "'Satoshi', sans-serif",
    cursor: 'pointer',
    transition: 'all 0.2s',
  }),

  // Grid
  profileGrid: {
    display: 'grid',
    gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))',
    gap: '16px',
  },
  cardWrapper: {
    position: 'relative' as const,
  },
  scoreBadge: {
    position: 'absolute' as const,
    bottom: '-8px',
    left: '50%',
    transform: 'translateX(-50%)',
    padding: '4px 14px',
    borderRadius: '12px',
    background: 'linear-gradient(135deg, #7c3aed 0%, #6d28d9 100%)',
    color: '#ffffff',
    fontSize: '13px',
    fontWeight: 700,
    fontFamily: "'Satoshi', sans-serif",
    boxShadow: '0 2px 8px rgba(124,58,237,0.4)',
    zIndex: 10,
    cursor: 'default',
    whiteSpace: 'nowrap' as const,
  },
  scoreTooltip: {
    position: 'absolute' as const,
    bottom: '32px',
    left: '50%',
    transform: 'translateX(-50%)',
    padding: '10px 14px',
    borderRadius: '10px',
    background: 'rgba(15,15,20,0.95)',
    border: '1px solid rgba(255,255,255,0.1)',
    color: '#ffffff',
    fontSize: '12px',
    fontFamily: "'Satoshi', sans-serif",
    zIndex: 20,
    whiteSpace: 'nowrap' as const,
    boxShadow: '0 4px 20px rgba(0,0,0,0.5)',
  },
  tooltipRow: {
    display: 'flex',
    justifyContent: 'space-between',
    gap: '16px',
    padding: '2px 0',
  },
  tooltipLabel: {
    color: 'rgba(255,255,255,0.6)',
  },
  tooltipValue: {
    color: '#a78bfa',
    fontWeight: 600,
  },

  // Load more
  loadMoreBtn: {
    display: 'block',
    margin: '32px auto 0',
    padding: '14px 32px',
    borderRadius: '14px',
    border: '1px solid rgba(255,255,255,0.1)',
    background: 'rgba(255,255,255,0.03)',
    color: '#ffffff',
    fontSize: '15px',
    fontWeight: 600,
    fontFamily: "'Satoshi', sans-serif",
    cursor: 'pointer',
    transition: 'all 0.2s',
  },

  // Empty state
  emptyState: {
    display: 'flex',
    flexDirection: 'column' as const,
    alignItems: 'center',
    justifyContent: 'center',
    padding: '80px 20px',
  },
  emptyIcon: {
    width: '80px',
    height: '80px',
    borderRadius: '50%',
    background: 'linear-gradient(135deg, rgba(168,85,247,0.15) 0%, rgba(168,85,247,0.05) 100%)',
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    marginBottom: '24px',
    fontSize: '32px',
  },
  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: '320px',
  },

  // Settings panel
  settingsPanel: {
    marginBottom: '24px',
    padding: '20px',
    borderRadius: '14px',
    background: 'rgba(255,255,255,0.02)',
    border: '1px solid rgba(255,255,255,0.06)',
  },
  settingsHeader: {
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: '16px',
  },
  settingsTitle: {
    fontFamily: "'Clash Display', sans-serif",
    fontSize: '18px',
    fontWeight: 600,
    color: '#ffffff',
  },
  weightRow: {
    display: 'flex',
    alignItems: 'center',
    gap: '12px',
    marginBottom: '8px',
  },
  weightLabel: {
    flex: '0 0 160px',
    fontSize: '13px',
    color: 'rgba(255,255,255,0.6)',
    fontFamily: "'Satoshi', sans-serif",
  },
  weightSlider: {
    flex: 1,
    accentColor: '#7c3aed',
  },
  weightValue: {
    flex: '0 0 36px',
    fontSize: '13px',
    color: '#a78bfa',
    fontWeight: 600,
    fontFamily: "'Satoshi', sans-serif",
    textAlign: 'right' as const,
  },

  // Loading
  loadingContainer: {
    display: 'flex',
    justifyContent: 'center',
    padding: '60px 20px',
    color: 'rgba(255,255,255,0.5)',
    fontFamily: "'Satoshi', sans-serif",
    fontSize: '15px',
  },

  // Gender pills
  genderPills: {
    display: 'flex',
    gap: '6px',
  },

  // Mode toggle
  modeToggleBar: {
    display: 'flex',
    gap: '4px',
    marginBottom: '20px',
    padding: '4px',
    borderRadius: '12px',
    background: 'rgba(255,255,255,0.03)',
    border: '1px solid rgba(255,255,255,0.06)',
    width: 'fit-content',
  },
  modeBtn: (active: boolean) => ({
    padding: '8px 20px',
    borderRadius: '10px',
    border: 'none',
    background: active ? 'rgba(124,58,237,0.2)' : 'transparent',
    color: active ? '#c084fc' : 'rgba(255,255,255,0.5)',
    fontSize: '14px',
    fontWeight: active ? 600 : 400,
    fontFamily: "'Satoshi', sans-serif",
    cursor: 'pointer',
    transition: 'all 0.2s',
  }),

  // API Matches section
  sectionTitle: {
    fontFamily: "'Clash Display', sans-serif",
    fontSize: '20px',
    fontWeight: 600,
    color: '#ffffff',
    margin: '0 0 16px 0',
  },
  sectionSubtitle: {
    fontFamily: "'Satoshi', sans-serif",
    fontSize: '13px',
    color: 'rgba(255,255,255,0.4)',
    margin: '-12px 0 16px 0',
  },
  sectionDivider: {
    margin: '32px 0',
    border: 'none',
    borderTop: '1px solid rgba(255,255,255,0.06)',
  },
  messageBtn: {
    display: 'inline-flex',
    alignItems: 'center',
    gap: '6px',
    marginTop: '8px',
    padding: '6px 14px',
    borderRadius: '8px',
    border: '1px solid rgba(168,85,247,0.3)',
    background: 'rgba(168,85,247,0.1)',
    color: '#c084fc',
    fontSize: '12px',
    fontWeight: 600,
    fontFamily: "'Satoshi', sans-serif",
    cursor: 'pointer',
    transition: 'all 0.2s',
  },
  matchCardWrapper: {
    position: 'relative' as const,
  },
  chatStatusBadge: {
    position: 'absolute' as const,
    bottom: '-8px',
    left: '50%',
    transform: 'translateX(-50%)',
    padding: '4px 14px',
    borderRadius: '12px',
    background: 'linear-gradient(135deg, #059669 0%, #047857 100%)',
    color: '#ffffff',
    fontSize: '12px',
    fontWeight: 600,
    fontFamily: "'Satoshi', sans-serif",
    boxShadow: '0 2px 8px rgba(5,150,105,0.4)',
    zIndex: 10,
    whiteSpace: 'nowrap' as const,
  },
};

const GENDER_OPTIONS = ['WOMAN', 'MAN', 'NON_BINARY'];
const DISTANCE_OPTIONS = [
  { label: '15mi', value: 15 },
  { label: '30mi', value: 30 },
  { label: '50mi', value: 50 },
  { label: '100mi', value: 100 },
  { label: 'Any', value: 0 },
];

const WEIGHT_LABELS: Record<string, string> = {
  verification: 'Verified profile',
  photoBase: 'Per photo (max 6)',
  photoVerified: 'Per verified photo',
  bioLong: 'Bio > 200 chars',
  bioMedium: 'Bio > 100 chars',
  bioShort: 'Bio > 30 chars',
  desiresMany: 'Desires >= 5',
  desiresSome: 'Desires >= 3',
  connectionGoals: 'Has goals',
  distanceClose: 'Within 15mi',
  distanceMedium: 'Within 30mi',
  distanceFar: 'Within 50mi',
  ageSweetSpot: 'Age 24-40',
  ageOk: 'Age 21-45',
  ageOutOfRange: 'Age out of range',
  theyLikedYou: 'They liked you',
  connectionDesires: 'Connection desires',
};

const BREAKDOWN_LABELS: Record<string, string> = {
  verification: 'Verified',
  photos: 'Photos',
  verifiedPhotos: 'Verified photos',
  bio: 'Bio quality',
  desires: 'Desires',
  connectionGoals: 'Goals',
  distance: 'Distance',
  age: 'Age',
  theyLikedYou: 'They liked you',
  connectionDesires: 'Connection',
};

export function MatchesPage() {
  const {
    matches, total, loading, filters, setFilters,
    fetchMatches, loadMore, removeMatch, hasMore,
    weights, updateWeights,
  } = useMatches();

  const navigate = useNavigate();
  const [matchMode, setMatchMode] = useState<'smart' | 'api'>('smart');

  // API Matches queries (only run when in 'api' mode)
  const { data: matchesData, loading: matchesLoading, refetch: refetchMatches } = useQuery(PROFILE_MATCHES_QUERY, {
    variables: { profileId: authManager.getProfileId(), limit: 25 },
    skip: matchMode !== 'api',
    fetchPolicy: 'cache-and-network',
  });

  const { data: connectionsData, loading: connectionsLoading, refetch: refetchConnections } = useQuery(GET_PROFILE_CONNECTIONS_QUERY, {
    variables: { limit: 25 },
    skip: matchMode !== 'api',
    fetchPolicy: 'cache-and-network',
  });

  const apiMatches = matchesData?.profile?.matches?.nodes || [];
  const apiMatchesPageInfo = matchesData?.profile?.matches?.pageInfo;
  const apiConnections = connectionsData?.connections?.nodes || [];
  const apiConnectionsPageInfo = connectionsData?.connections?.pageInfo;

  const [selectedProfileId, setSelectedProfileId] = useState<string | null>(null);
  const [hoveredScore, setHoveredScore] = useState<string | null>(null);
  const [showSettings, setShowSettings] = useState(false);
  const [localWeights, setLocalWeights] = useState<MatchWeights | null>(null);
  const [refreshedPhotos, setRefreshedPhotos] = useState<Record<string, any[]>>({});
  const refreshedIdsRef = useRef<Set<string>>(new Set());
  const refreshQueueRef = useRef<Set<string>>(new Set());
  const isProcessingRef = useRef(false);

  // Process the refresh queue one at a time
  const processRefreshQueue = useCallback(async () => {
    if (isProcessingRef.current) return;
    isProcessingRef.current = true;

    while (refreshQueueRef.current.size > 0) {
      const profileId = refreshQueueRef.current.values().next().value!;
      refreshQueueRef.current.delete(profileId);

      try {
        const result = await apolloClient.query({
          query: PROFILE_QUERY,
          variables: { profileId },
          fetchPolicy: 'network-only',
        });
        const fresh = result.data?.profile;
        if (fresh?.photos?.length) {
          setRefreshedPhotos(prev => ({ ...prev, [profileId]: fresh.photos }));
          fetch('/api/discovered-profiles/update-photos', {
            method: 'PUT',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ profileId, photos: fresh.photos }),
          }).catch(() => {});
        }
      } catch (e) {
        // silently skip failed refreshes
      }
      await new Promise(r => setTimeout(r, 150));
    }

    isProcessingRef.current = false;
  }, []);

  // Queue a profile for photo refresh when it enters the viewport
  const queueRefresh = useCallback((profileId: string) => {
    if (refreshedIdsRef.current.has(profileId)) return;
    refreshedIdsRef.current.add(profileId);
    refreshQueueRef.current.add(profileId);
    processRefreshQueue();
  }, [processRefreshQueue]);

  // IntersectionObserver to detect cards entering viewport
  const observerRef = useRef<IntersectionObserver | null>(null);
  useEffect(() => {
    observerRef.current = new IntersectionObserver(
      (entries) => {
        for (const entry of entries) {
          if (entry.isIntersecting) {
            const profileId = (entry.target as HTMLElement).dataset.profileId;
            if (profileId) queueRefresh(profileId);
          }
        }
      },
      { rootMargin: '200px' }
    );
    return () => observerRef.current?.disconnect();
  }, [queueRefresh]);

  // Ref callback for each card to observe/unobserve
  const cardRefs = useRef<Map<string, HTMLDivElement>>(new Map());
  const setCardRef = useCallback((profileId: string, el: HTMLDivElement | null) => {
    const prev = cardRefs.current.get(profileId);
    if (prev && observerRef.current) observerRef.current.unobserve(prev);
    if (el) {
      cardRefs.current.set(profileId, el);
      if (observerRef.current) observerRef.current.observe(el);
    } else {
      cardRefs.current.delete(profileId);
    }
  }, []);

  // Merge refreshed photos into match profiles
  const displayMatches = useMemo(() => matches.map(m => {
    const freshPhotos = refreshedPhotos[m.id];
    return freshPhotos ? { ...m, photos: freshPhotos } : m;
  }), [matches, refreshedPhotos]);

  const activeFiltersCount = [
    filters.search, filters.minAge, filters.maxAge,
    filters.maxDistance, filters.gender,
    filters.verifiedOnly, filters.theyLikedOnly,
  ].filter(Boolean).length;

  const handleFilterChange = useCallback((key: keyof MatchFilters, value: any) => {
    setFilters((prev: MatchFilters) => ({ ...prev, [key]: value || undefined }));
  }, [setFilters]);

  const clearFilters = useCallback(() => {
    setFilters({});
  }, [setFilters]);

  const handleWeightChange = useCallback((key: string, value: number) => {
    setLocalWeights(prev => ({ ...(prev || weights || {}), [key]: value }));
  }, [weights]);

  const saveWeights = useCallback(() => {
    if (localWeights) {
      updateWeights(localWeights);
    }
  }, [localWeights, updateWeights]);

  const resetWeights = useCallback(() => {
    setLocalWeights(null);
    updateWeights({});
  }, [updateWeights]);

  const displayWeights = localWeights || weights || {};

  return (
    <div style={styles.container}>
      {/* Header */}
      <div style={styles.header}>
        <h1 style={styles.title}>{matchMode === 'smart' ? 'Smart Matches' : 'API Matches'}</h1>
        <p style={styles.subtitle}>
          {matchMode === 'smart'
            ? `${total} ranked profiles from your discovery cache`
            : `${apiMatchesPageInfo?.total ?? apiMatches.length} matches, ${apiConnectionsPageInfo?.total ?? apiConnections.length} connections from Feeld API`}
        </p>
        <div style={styles.headerActions}>
          <button
            style={styles.iconBtn}
            onClick={() => {
              if (matchMode === 'smart') fetchMatches();
              else { refetchMatches(); refetchConnections(); }
            }}
            title="Refresh"
          >
            &#x21bb;
          </button>
          {matchMode === 'smart' && (
            <button
              style={{
                ...styles.iconBtn,
                ...(showSettings ? { background: 'rgba(124,58,237,0.15)', borderColor: 'rgba(124,58,237,0.3)', color: '#a78bfa' } : {}),
              }}
              onClick={() => {
                setShowSettings(v => !v);
                if (!localWeights && weights) setLocalWeights({ ...weights });
              }}
              title="Scoring Settings"
            >
              &#x2699;
            </button>
          )}
        </div>
      </div>

      {/* Mode Toggle */}
      <div style={styles.modeToggleBar}>
        <button
          style={styles.modeBtn(matchMode === 'smart')}
          onClick={() => setMatchMode('smart')}
        >
          Smart Matches
        </button>
        <button
          style={styles.modeBtn(matchMode === 'api')}
          onClick={() => setMatchMode('api')}
        >
          API Matches
        </button>
      </div>

      {/* ===== SMART MATCHES MODE ===== */}
      {matchMode === 'smart' && <>

      {/* Scoring Settings */}
      {showSettings && (
        <div style={styles.settingsPanel}>
          <div style={styles.settingsHeader}>
            <span style={styles.settingsTitle}>Scoring Weights</span>
            <div style={{ display: 'flex', gap: '8px' }}>
              <button style={styles.clearBtn} onClick={resetWeights}>Reset</button>
              <button
                style={{ ...styles.toggleBtn(true), background: 'rgba(124,58,237,0.2)' }}
                onClick={saveWeights}
              >
                Apply
              </button>
            </div>
          </div>
          {Object.entries(WEIGHT_LABELS).map(([key, label]) => (
            <div key={key} style={styles.weightRow}>
              <span style={styles.weightLabel}>{label}</span>
              <input
                type="range"
                min="0"
                max="50"
                value={displayWeights[key] ?? 0}
                onChange={e => handleWeightChange(key, parseInt(e.target.value))}
                style={styles.weightSlider}
              />
              <span style={styles.weightValue}>{displayWeights[key] ?? 0}</span>
            </div>
          ))}
        </div>
      )}

      {/* Filter Bar */}
      <div style={styles.filterBar}>
        <input
          type="text"
          placeholder="Search name or bio..."
          value={filters.search || ''}
          onChange={e => handleFilterChange('search', e.target.value)}
          style={styles.searchInput}
        />
        <span style={styles.filterLabel}>Age</span>
        <input
          type="number"
          placeholder="Min"
          value={filters.minAge || ''}
          onChange={e => handleFilterChange('minAge', e.target.value ? parseInt(e.target.value) : undefined)}
          style={styles.numberInput}
        />
        <span style={{ color: 'rgba(255,255,255,0.3)' }}>-</span>
        <input
          type="number"
          placeholder="Max"
          value={filters.maxAge || ''}
          onChange={e => handleFilterChange('maxAge', e.target.value ? parseInt(e.target.value) : undefined)}
          style={styles.numberInput}
        />
        <select
          value={filters.maxDistance || 0}
          onChange={e => handleFilterChange('maxDistance', parseInt(e.target.value) || undefined)}
          style={styles.select}
        >
          <option value={0}>Any distance</option>
          {DISTANCE_OPTIONS.filter(d => d.value > 0).map(d => (
            <option key={d.value} value={d.value}>{d.label}</option>
          ))}
        </select>
        <div style={styles.genderPills}>
          {GENDER_OPTIONS.map(g => {
            const selected = filters.gender?.split(',').includes(g);
            return (
              <button
                key={g}
                style={styles.toggleBtn(!!selected)}
                onClick={() => {
                  const current = filters.gender ? filters.gender.split(',') : [];
                  const next = selected
                    ? current.filter(c => c !== g)
                    : [...current, g];
                  handleFilterChange('gender', next.length > 0 ? next.join(',') : undefined);
                }}
              >
                {g === 'NON_BINARY' ? 'NB' : g.charAt(0) + g.slice(1).toLowerCase()}
              </button>
            );
          })}
        </div>
        <button
          style={styles.toggleBtn(!!filters.verifiedOnly)}
          onClick={() => handleFilterChange('verifiedOnly', !filters.verifiedOnly || undefined)}
        >
          Verified
        </button>
        <button
          style={styles.toggleBtn(!!filters.theyLikedOnly)}
          onClick={() => handleFilterChange('theyLikedOnly', !filters.theyLikedOnly || undefined)}
        >
          Liked you
        </button>
        {activeFiltersCount > 0 && (
          <button style={styles.clearBtn} onClick={clearFilters}>
            Clear ({activeFiltersCount})
          </button>
        )}
      </div>

      {/* Sort Bar */}
      <div style={styles.sortBar}>
        <span style={styles.sortLabel}>Sort:</span>
        {(['score', 'distance', 'recent'] as const).map(s => (
          <button
            key={s}
            style={styles.sortBtn((filters.sort || 'score') === s)}
            onClick={() => handleFilterChange('sort', s === 'score' ? undefined : s)}
          >
            {s === 'score' ? 'Score' : s === 'distance' ? 'Distance' : 'Recent'}
          </button>
        ))}
      </div>

      {/* Loading */}
      {loading && matches.length === 0 && (
        <div style={styles.loadingContainer}>Loading matches...</div>
      )}

      {/* Empty State */}
      {!loading && matches.length === 0 && (
        <div style={styles.emptyState}>
          <div style={styles.emptyIcon}>
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" style={{ width: 36, height: 36, color: '#a78bfa' }}>
              <path strokeLinecap="round" strokeLinejoin="round" d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09zM18.259 8.715L18 9.75l-.259-1.035a3.375 3.375 0 00-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 002.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 002.455 2.456L21.75 6l-1.036.259a3.375 3.375 0 00-2.455 2.456zM16.894 20.567L16.5 21.75l-.394-1.183a2.25 2.25 0 00-1.423-1.423L13.5 18.75l1.183-.394a2.25 2.25 0 001.423-1.423l.394-1.183.394 1.183a2.25 2.25 0 001.423 1.423l1.183.394-1.183.394a2.25 2.25 0 00-1.423 1.423z" />
            </svg>
          </div>
          <div style={styles.emptyTitle}>No matches found</div>
          <div style={styles.emptyText}>
            {activeFiltersCount > 0
              ? 'Try adjusting your filters to see more profiles.'
              : 'Scan profiles on the Discover page to build your match pool.'}
          </div>
        </div>
      )}

      {/* Profile Grid */}
      {displayMatches.length > 0 && (
        <div style={styles.profileGrid}>
          {displayMatches.map((profile, index) => (
            <div
              key={profile.id}
              style={styles.cardWrapper}
              data-profile-id={profile.id}
              ref={(el) => setCardRef(profile.id, el)}
            >
              <ProfileCard
                profile={profile as any}
                onClick={() => setSelectedProfileId(profile.id)}
                index={index}
              />
              {/* Score badge */}
              <div
                style={styles.scoreBadge}
                onMouseEnter={() => setHoveredScore(profile.id)}
                onMouseLeave={() => setHoveredScore(null)}
              >
                {profile._score} pts
                {profile.interactionStatus?.theirs === 'LIKED' && ' \u2764'}
              </div>
              {/* Score tooltip */}
              {hoveredScore === profile.id && profile._scoreBreakdown && (
                <div style={styles.scoreTooltip}>
                  {Object.entries(profile._scoreBreakdown).map(([key, val]) => (
                    <div key={key} style={styles.tooltipRow}>
                      <span style={styles.tooltipLabel}>{BREAKDOWN_LABELS[key] || key}</span>
                      <span style={styles.tooltipValue}>+{val}</span>
                    </div>
                  ))}
                  {Object.keys(profile._scoreBreakdown).length === 0 && (
                    <div style={{ color: 'rgba(255,255,255,0.4)' }}>No scoring factors</div>
                  )}
                </div>
              )}
            </div>
          ))}
        </div>
      )}

      {/* Load More */}
      {hasMore && !loading && (
        <button style={styles.loadMoreBtn} onClick={loadMore}>
          Load More ({matches.length} of {total})
        </button>
      )}
      {loading && matches.length > 0 && (
        <div style={styles.loadingContainer}>Loading more...</div>
      )}

      </>}

      {/* ===== API MATCHES MODE ===== */}
      {matchMode === 'api' && (
        <>
          {/* Loading */}
          {(matchesLoading || connectionsLoading) && apiMatches.length === 0 && apiConnections.length === 0 && (
            <div style={styles.loadingContainer}>Loading API matches...</div>
          )}

          {/* Matches Section */}
          {apiMatches.length > 0 && (
            <>
              <h2 style={styles.sectionTitle}>
                Matches {apiMatchesPageInfo?.total != null && `(${apiMatchesPageInfo.total})`}
              </h2>
              <div style={styles.profileGrid}>
                {apiMatches.map((node: any, index: number) => (
                  <div key={node.profile?.id || index} style={styles.matchCardWrapper}>
                    <ProfileCard
                      profile={node.profile}
                      onClick={() => node.profile?.id && setSelectedProfileId(node.profile.id)}
                      index={index}
                    />
                    {node.chat?.streamChatId && (
                      <div style={styles.chatStatusBadge}>
                        {safeText(node.chat.status) || 'Matched'}
                      </div>
                    )}
                    {node.chat?.streamChatId && (
                      <div style={{ textAlign: 'center', marginTop: '16px' }}>
                        <button
                          style={styles.messageBtn}
                          onClick={() => navigate(`/chat/${node.chat.streamChatId}`)}
                        >
                          Message
                        </button>
                      </div>
                    )}
                  </div>
                ))}
              </div>
            </>
          )}

          {/* Divider between sections */}
          {apiMatches.length > 0 && apiConnections.length > 0 && (
            <hr style={styles.sectionDivider} />
          )}

          {/* Connections Section */}
          {apiConnections.length > 0 && (
            <>
              <h2 style={styles.sectionTitle}>
                Connections {apiConnectionsPageInfo?.total != null && `(${apiConnectionsPageInfo.total})`}
              </h2>
              <div style={styles.profileGrid}>
                {apiConnections.map((profile: any, index: number) => (
                  <div key={profile.imaginaryName + '-' + index} style={styles.matchCardWrapper}>
                    <ProfileCard
                      profile={profile}
                      onClick={() => profile.id && setSelectedProfileId(profile.id)}
                      index={index}
                    />
                  </div>
                ))}
              </div>
            </>
          )}

          {/* Empty State */}
          {!matchesLoading && !connectionsLoading && apiMatches.length === 0 && apiConnections.length === 0 && (
            <div style={styles.emptyState}>
              <div style={styles.emptyIcon}>
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" style={{ width: 36, height: 36, color: '#a78bfa' }}>
                  <path strokeLinecap="round" strokeLinejoin="round" d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09zM18.259 8.715L18 9.75l-.259-1.035a3.375 3.375 0 00-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 002.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 002.455 2.456L21.75 6l-1.036.259a3.375 3.375 0 00-2.455 2.456zM16.894 20.567L16.5 21.75l-.394-1.183a2.25 2.25 0 00-1.423-1.423L13.5 18.75l1.183-.394a2.25 2.25 0 001.423-1.423l.394-1.183.394 1.183a2.25 2.25 0 001.423 1.423l1.183.394-1.183.394a2.25 2.25 0 00-1.423 1.423z" />
                </svg>
              </div>
              <div style={styles.emptyTitle}>No API matches found</div>
              <div style={styles.emptyText}>
                No matches or connections returned from the Feeld API.
              </div>
            </div>
          )}
        </>
      )}

      {/* Profile Detail Modal */}
      {selectedProfileId && (
        <ProfileDetailModal
          profileId={selectedProfileId}
          onClose={() => setSelectedProfileId(null)}
          onMatch={() => {
            removeMatch(selectedProfileId);
            setSelectedProfileId(null);
          }}
        />
      )}
    </div>
  );
}
