'use client';

import { useState, useEffect, useRef } from 'react';
import { createPortal } from 'react-dom';
import ReviewAnalytics from './ReviewAnalytics';

interface Review {
  author: string;
  rating: number;
  text: string | null;
  date_text: string;
  avatar_url: string | null;
  profile_url: string | null;
  review_id: string;
}

export interface JobStatus {
  job_id: string;
  status: 'pending' | 'running' | 'completed' | 'failed' | 'partial';
  url: string;
  created_at: string;
  started_at: string | null;
  completed_at: string | null;
  updated_at: string | null;  // Last update time for progress tracking
  reviews_count: number | null;
  total_reviews: number | null;
  scrape_time: number | null;
  error_message: string | null;
  // Business metadata for tracking and comparison
  business_name: string | null;
  business_address: string | null;
  business_category: string | null;
  rating_snapshot: number | null;
  total_reviews_snapshot: number | null;
  // Review topics extracted from Google Maps
  review_topics: { topic: string; count: number }[] | null;
}

interface ScraperTestProps {
  onJobsChange?: (jobs: JobStatus[]) => void;
  onSelectReviews?: (reviews: Review[], businessName: string, jobId: string) => void;
}

export default function ScraperTest({ onJobsChange, onSelectReviews }: ScraperTestProps = {}) {
  // Split search fields
  const [businessNameQuery, setBusinessNameQuery] = useState('');
  const [locationQuery, setLocationQuery] = useState('');
  const [detectedLocation, setDetectedLocation] = useState<{ city: string; country: string } | null>(null);
  const [searchedQuery, setSearchedQuery] = useState('');
  const [showMapClickModal, setShowMapClickModal] = useState(false);
  const [jobs, setJobs] = useState<Map<string, JobStatus>>(new Map());
  const [activeJobId, setActiveJobId] = useState<string | null>(null);
  const [reviews, setReviews] = useState<Review[]>([]);
  const [error, setError] = useState('');
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [showAnalytics, setShowAnalytics] = useState(false);
  const [isLoadingReviews, setIsLoadingReviews] = useState(false);
  const [showConfirmModal, setShowConfirmModal] = useState(false);
  const [isCheckingReviews, setIsCheckingReviews] = useState(false);
  const [hasReviews, setHasReviews] = useState<boolean | null>(null);
  const [availableReviewCount, setAvailableReviewCount] = useState<number | null>(null);
  const [businessName, setBusinessName] = useState<string | null>(null);
  const [businessAddress, setBusinessAddress] = useState<string | null>(null);
  const [businessRating, setBusinessRating] = useState<number | null>(null);
  const [businessImage, setBusinessImage] = useState<string | null>(null);
  const [businessCategory, setBusinessCategory] = useState<string | null>(null);
  // Session handoff - store session_id from validation for browser reuse
  const [sessionId, setSessionId] = useState<string | null>(null);
  const [sessionExpiresIn, setSessionExpiresIn] = useState<number | null>(null);

  // Scraper version selection - v1.1.0 is default (multi-sort enabled)
  const AVAILABLE_VERSIONS = [
    { value: '1.1.0', label: 'v1.1.0 (Multi-Sort)', description: 'Bypasses ~1000 review limit' },
    { value: '1.0.0', label: 'v1.0.0 (Standard)', description: 'Original scraper' },
  ];
  const [scraperVersion, setScraperVersion] = useState('1.1.0');

  const [userFingerprint, setUserFingerprint] = useState<{
    geolocation?: {lat: number, lng: number},
    userAgent?: string,
    viewport?: {width: number, height: number},
    timezone?: string,
    language?: string,
    platform?: string
  }>({});
  const debounceRef = useRef<NodeJS.Timeout | null>(null);

  // Collect browser fingerprint on mount (no permissions needed)
  useEffect(() => {
    const collectFingerprint = async () => {
      const fingerprint: typeof userFingerprint = {};

      // User agent
      fingerprint.userAgent = navigator.userAgent;

      // Screen/viewport size
      fingerprint.viewport = {
        width: window.screen.width,
        height: window.screen.height
      };

      // Timezone
      fingerprint.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;

      // Language
      fingerprint.language = navigator.language;

      // Platform
      fingerprint.platform = navigator.platform;

      // Get approximate location from IP (no permission needed)
      try {
        const response = await fetch('https://ipapi.co/json/', {
          signal: AbortSignal.timeout(3000)
        });
        if (response.ok) {
          const data = await response.json();
          if (data.latitude && data.longitude) {
            fingerprint.geolocation = {
              lat: data.latitude,
              lng: data.longitude
            };
            // Store detected city and country for location field
            if (data.city && data.country_name) {
              setDetectedLocation({
                city: data.city,
                country: data.country_name
              });
              // Auto-fill location field
              setLocationQuery(`${data.city}, ${data.country_name}`);
            }
            console.log('IP location:', data.city, data.country_name);
          }
        }
      } catch (error) {
        console.log('IP geolocation not available');
      }

      setUserFingerprint(fingerprint);
      console.log('Browser fingerprint:', fingerprint);
    };

    collectFingerprint();
  }, []);

  const pollingIntervals = useRef<Map<string, NodeJS.Timeout>>(new Map());
  const abortControllerRef = useRef<AbortController | null>(null);

  // localStorage key for persisting jobs
  const JOBS_STORAGE_KEY = 'reviewiq_active_jobs';

  // Reset search state after job launch
  const resetSearchState = () => {
    setBusinessNameQuery('');
    // Keep location as it's auto-detected
    setSearchedQuery('');
    setHasReviews(null);
    setAvailableReviewCount(null);
    setBusinessName(null);
    setBusinessAddress(null);
    setBusinessRating(null);
    setBusinessImage(null);
    setBusinessCategory(null);
  };

  // Persist jobs to localStorage whenever they change
  useEffect(() => {
    if (jobs.size > 0) {
      const jobsArray = Array.from(jobs.values());
      localStorage.setItem(JOBS_STORAGE_KEY, JSON.stringify(jobsArray));
    }
  }, [jobs]);

  // Restore jobs from localStorage on mount
  useEffect(() => {
    const restoreJobs = async () => {
      try {
        const stored = localStorage.getItem(JOBS_STORAGE_KEY);
        if (!stored) return;

        const storedJobs: JobStatus[] = JSON.parse(stored);
        if (!Array.isArray(storedJobs) || storedJobs.length === 0) return;

        // Filter out jobs older than 24 hours
        const oneDayAgo = Date.now() - 24 * 60 * 60 * 1000;
        const recentJobs = storedJobs.filter(job => {
          const createdAt = new Date(job.created_at).getTime();
          return createdAt > oneDayAgo;
        });

        if (recentJobs.length === 0) {
          localStorage.removeItem(JOBS_STORAGE_KEY);
          return;
        }

        // Fetch current status for each job
        const jobsMap = new Map<string, JobStatus>();
        for (const job of recentJobs) {
          try {
            const response = await fetch(`/api/jobs/${job.job_id}`);
            if (response.ok) {
              const freshJob = await response.json();
              jobsMap.set(job.job_id, freshJob);

              // Resume polling for non-terminal jobs
              if (freshJob.status === 'pending' || freshJob.status === 'running') {
                startPolling(job.job_id);
              }
            }
          } catch (err) {
            console.error('Failed to restore job', job.job_id, err);
          }
        }

        if (jobsMap.size > 0) {
          setJobs(jobsMap);
        }
      } catch (err) {
        console.error('Failed to restore jobs from localStorage', err);
      }
    };

    restoreJobs();
  }, []);

  // Remove a job from the list and localStorage
  const removeJob = (jobId: string) => {
    // Stop polling if running
    const interval = pollingIntervals.current.get(jobId);
    if (interval) {
      clearInterval(interval);
      pollingIntervals.current.delete(jobId);
    }

    // Remove from state
    setJobs(prev => {
      const newMap = new Map(prev);
      newMap.delete(jobId);

      // Update localStorage
      if (newMap.size === 0) {
        localStorage.removeItem(JOBS_STORAGE_KEY);
      } else {
        localStorage.setItem(JOBS_STORAGE_KEY, JSON.stringify(Array.from(newMap.values())));
      }

      return newMap;
    });

    // Clear active job if it was removed
    if (activeJobId === jobId) {
      setActiveJobId(null);
      setReviews([]);
    }
  };

  // Build full search query from business name + location
  const buildSearchQuery = () => {
    const name = businessNameQuery.trim();
    const location = locationQuery.trim();
    if (name && location) {
      return `"${name}" ${location}`;
    } else if (name) {
      return name;
    }
    return '';
  };

  // Debounce: update map preview as user types (500ms after stopping)
  useEffect(() => {
    const query = buildSearchQuery();
    if (query.length >= 2) {
      if (debounceRef.current) {
        clearTimeout(debounceRef.current);
      }

      debounceRef.current = setTimeout(() => {
        setSearchedQuery(query);
      }, 500);

      return () => {
        if (debounceRef.current) {
          clearTimeout(debounceRef.current);
        }
      };
    }
  }, [businessNameQuery, locationQuery]);

  // Clear validation results when user starts typing a new search
  useEffect(() => {
    const currentQuery = buildSearchQuery();
    // If current query is different from searchedQuery, clear results
    if (currentQuery !== searchedQuery && searchedQuery) {
      // Abort any pending validation request
      if (abortControllerRef.current) {
        abortControllerRef.current.abort();
      }
      setHasReviews(null);
      setAvailableReviewCount(null);
      setBusinessName(null);
      setBusinessAddress(null);
      setBusinessRating(null);
      setBusinessImage(null);
      setBusinessCategory(null);
    }
  }, [businessNameQuery, locationQuery, searchedQuery]);

  // Notify parent when jobs change
  useEffect(() => {
    if (onJobsChange) {
      onJobsChange(Array.from(jobs.values()));
    }
  }, [jobs, onJobsChange]);

  // Check for reviews function (called manually when user clicks Validate)
  // Uses session handoff - keeps browser alive for reuse during scraping
  const checkReviews = async (query: string) => {
    // Abort any previous validation request
    if (abortControllerRef.current) {
      abortControllerRef.current.abort();
    }

    setIsCheckingReviews(true);
    setHasReviews(null);
    setAvailableReviewCount(null);
    setBusinessName(null);
    setBusinessAddress(null);
    setBusinessRating(null);
    setBusinessImage(null);
    setBusinessCategory(null);
    setSessionId(null);
    setSessionExpiresIn(null);
    setError('');

    // Create new abort controller with 60 second timeout (validation can be slow)
    const controller = new AbortController();
    abortControllerRef.current = controller;
    const timeoutId = setTimeout(() => controller.abort(), 60000);

    try {
      // Force English with hl=en parameter
      const url = `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(query)}&hl=en`;

      // Use session validation endpoint - keeps browser alive for reuse
      const response = await fetch('/api/sessions/validate', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          url,
          geolocation: userFingerprint.geolocation,
          browser_fingerprint: userFingerprint,  // Pass full fingerprint
          session_ttl: 300  // 5 minute session TTL
        }),
        signal: controller.signal,
      });

      clearTimeout(timeoutId);

      const data = await response.json();

      if (response.ok && data.success) {
        const businessInfo = data.business_info || {};
        setHasReviews(data.total_reviews > 0);
        setAvailableReviewCount(data.total_reviews || 0);
        setBusinessName(businessInfo.name);
        setBusinessAddress(businessInfo.address);
        setBusinessRating(businessInfo.rating);
        setBusinessCategory(businessInfo.category);
        // Store session_id for browser reuse during scraping
        if (data.session_id) {
          setSessionId(data.session_id);
          setSessionExpiresIn(data.expires_in);
          console.log(`Session created: ${data.session_id} (expires in ${data.expires_in}s)`);
        }
      } else {
        console.error('Failed to get business info:', data.error);
        // Business not found
        setHasReviews(false);
        setAvailableReviewCount(0);
      }
    } catch (err) {
      clearTimeout(timeoutId);

      // Check if this is a timeout abort vs user-initiated abort
      if (err instanceof Error && err.name === 'AbortError') {
        // Check if it was a timeout (controller still matches) or user started new search
        if (abortControllerRef.current === controller) {
          // Timeout - show error
          console.error('Validation timed out');
          setError('Validation timed out. Please try again.');
          setHasReviews(false);
          setAvailableReviewCount(0);
        } else {
          // User started a new search - just return silently
          console.log('Validation cancelled (new validation started)');
          return;
        }
      } else {
        console.error('Error getting business info:', err);
        // Error occurred
        setHasReviews(false);
        setAvailableReviewCount(0);
      }
    } finally {
      clearTimeout(timeoutId);
      // Always clear loading state (even on timeout)
      setIsCheckingReviews(false);
    }
  };

  // Poll job status for all active jobs
  const startPolling = (jobId: string) => {
    // Don't start if already polling this job
    if (pollingIntervals.current.has(jobId)) return;

    const pollInterval = setInterval(async () => {
      try {
        const response = await fetch(`/api/jobs/${jobId}`);
        const data = await response.json();

        // Update job in map
        setJobs(prev => {
          const newMap = new Map(prev);
          newMap.set(jobId, data);
          return newMap;
        });

        // Stop polling if job is done (completed, failed, or partial)
        if (data.status === 'completed' || data.status === 'failed' || data.status === 'partial') {
          const interval = pollingIntervals.current.get(jobId);
          if (interval) {
            clearInterval(interval);
            pollingIntervals.current.delete(jobId);
          }
        }
      } catch (err) {
        console.error('Poll error for job', jobId, err);
      }
    }, 2000); // Poll every 2 seconds

    pollingIntervals.current.set(jobId, pollInterval);
  };

  // Cleanup polling intervals and abort controllers on unmount
  useEffect(() => {
    return () => {
      pollingIntervals.current.forEach(interval => clearInterval(interval));
      pollingIntervals.current.clear();
      if (abortControllerRef.current) {
        abortControllerRef.current.abort();
      }
    };
  }, []);

  const handleSearch = () => {
    const query = buildSearchQuery();
    if (query.length < 2 || !businessNameQuery.trim()) return;

    // Clear any pending debounce
    if (debounceRef.current) {
      clearTimeout(debounceRef.current);
    }

    // Immediately update map preview and trigger validation
    setSearchedQuery(query);
    checkReviews(query);
  };

  const handlePreviewBusiness = (e: React.FormEvent) => {
    e.preventDefault();
    setShowConfirmModal(true);
  };

  const handleConfirmScrape = async () => {
    setError('');
    setIsSubmitting(true);
    setShowConfirmModal(false);

    // Use the search query to create a Google Maps search URL (force English)
    const url = `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(searchedQuery)}&hl=en`;

    try {
      // Build request body - include session_id if available for browser reuse
      const requestBody: Record<string, unknown> = {
        url,
        business_name: businessName,
        business_address: businessAddress,
        rating_snapshot: businessRating,
        total_reviews_snapshot: availableReviewCount,
        geolocation: userFingerprint.geolocation,
        browser_fingerprint: userFingerprint,  // Pass full fingerprint
        // Google Reviews scraper (this component is specific to Google Reviews)
        job_type: 'google-reviews',
        scraper_version: scraperVersion,  // Selected scraper version
      };

      // If we have a session_id from validation, use it for browser reuse
      // This saves 4-16 seconds by skipping navigation
      if (sessionId) {
        requestBody.session_id = sessionId;
        console.log(`Using session handoff: ${sessionId}`);
      }

      const response = await fetch('/api/scrape', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(requestBody),
      });

      const data = await response.json();

      if (!response.ok) {
        throw new Error(data.error || 'Failed to start scraping');
      }

      // Add job to Map with initial status
      setJobs(prev => {
        const newMap = new Map(prev);
        newMap.set(data.job_id, {
          job_id: data.job_id,
          status: 'pending',
          url: url,
          created_at: new Date().toISOString(),
          started_at: null,
          completed_at: null,
          updated_at: new Date().toISOString(),
          reviews_count: null,
          total_reviews: null,
          scrape_time: null,
          error_message: null,
          business_name: businessName,
          business_address: businessAddress,
          business_category: businessCategory,
          rating_snapshot: businessRating,
          total_reviews_snapshot: availableReviewCount,
          review_topics: null,  // Will be populated when job completes
        });
        return newMap;
      });

      // Set as active job and start polling
      setActiveJobId(data.job_id);
      startPolling(data.job_id);

      // Reset search state to allow starting another job
      resetSearchState();

    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to submit job');
    } finally {
      setIsSubmitting(false);
    }
  };

  const getStatusColor = (status: string) => {
    switch (status) {
      case 'completed': return 'text-green-700';
      case 'running': return 'text-blue-700';
      case 'failed': return 'text-red-700';
      case 'partial': return 'text-orange-700';
      default: return 'text-gray-800';
    }
  };

  const getStatusIcon = (status: string) => {
    switch (status) {
      case 'completed':
        return (
          <svg className="w-5 h-5 text-green-500" fill="currentColor" viewBox="0 0 20 20">
            <path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
          </svg>
        );
      case 'running':
        return <div className="w-5 h-5 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" />;
      case 'failed':
        return (
          <svg className="w-5 h-5 text-red-500" fill="currentColor" viewBox="0 0 20 20">
            <path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clipRule="evenodd" />
          </svg>
        );
      case 'partial':
        return (
          <svg className="w-5 h-5 text-orange-500" fill="currentColor" viewBox="0 0 20 20">
            <path fillRule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clipRule="evenodd" />
          </svg>
        );
      default:
        return (
          <svg className="w-5 h-5 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
            <path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clipRule="evenodd" />
          </svg>
        );
    }
  };

  // Google Maps embed URL for iframe preview
  const embedUrl = searchedQuery
    ? `https://maps.google.com/maps?q=${encodeURIComponent(searchedQuery)}&output=embed&z=15`
    : '';

  // Google Maps link for opening in new tab
  const googleMapsUrl = searchedQuery
    ? `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(searchedQuery)}`
    : '';

  const searchInputRef = useRef<HTMLInputElement>(null);

  // Test URLs at different scales (split into business name + location)
  const testUrls = [
    { name: '🏪 Small (~79)', businessName: 'R. Fleitas Peluqueros', location: 'Las Palmas, Spain' },
    { name: '🚗 Medium (~589)', businessName: 'ClickRent', location: 'Gran Canaria, Spain' },
    { name: '🏥 Large (~2000+)', businessName: 'Hospital Universitario Doctor Negrín', location: 'Las Palmas, Spain' },
    { name: '🛒 Alcampo', businessName: 'Alcampo Hipermarket', location: 'Las Palmas, Spain' },
  ];

  return (
    <div className="w-full max-w-4xl mx-auto">
      {/* Test URL Quick Select */}
      <div className="mb-4 p-3 bg-gray-50 border-2 border-gray-200 rounded-xl">
        <div className="flex items-center gap-2 mb-2">
          <span className="text-xs font-semibold text-gray-500 uppercase tracking-wide">Quick Test:</span>
        </div>
        <div className="flex flex-wrap gap-2">
          {testUrls.map((test, idx) => (
            <button
              key={idx}
              onClick={() => {
                setBusinessNameQuery(test.businessName);
                setLocationQuery(test.location);
                const fullQuery = `"${test.businessName}" ${test.location}`;
                setSearchedQuery(fullQuery);
                checkReviews(fullQuery);
              }}
              className="px-3 py-1.5 text-sm bg-white border-2 border-gray-300 rounded-lg hover:border-blue-500 hover:bg-blue-50 transition-all font-medium text-gray-700"
            >
              {test.name}
            </button>
          ))}
        </div>
      </div>

      {/* Search Interface - Horizontal Layout */}
      <>
          <div className="mb-4 flex gap-2 items-end">
            {/* Business Name Field */}
            <div className="flex-1">
              <label className="block text-xs font-semibold text-gray-600 mb-1">
                Business Name <span className="text-red-500">*</span>
              </label>
              <div className="relative">
                <div className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400">
                  <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
                  </svg>
                </div>
                <input
                  ref={searchInputRef}
                  type="text"
                  value={businessNameQuery}
                  onChange={(e) => setBusinessNameQuery(e.target.value)}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter' && businessNameQuery.trim() && !isCheckingReviews) {
                      e.preventDefault();
                      handleSearch();
                    }
                  }}
                  placeholder="Starbucks, McDonald's..."
                  className="w-full pl-9 pr-3 py-2.5 text-gray-900 bg-white border-2 border-gray-200 rounded-lg focus:border-blue-500 focus:ring-2 focus:ring-blue-100 outline-none transition-all text-sm"
                />
              </div>
            </div>

            {/* Location Field */}
            <div className="flex-1">
              <label className="block text-xs font-semibold text-gray-600 mb-1">
                Location
                {detectedLocation && (
                  <span className="ml-1 text-xs font-normal text-green-600">✓</span>
                )}
              </label>
              <div className="relative">
                <div className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400">
                  <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
                  </svg>
                </div>
                <input
                  type="text"
                  value={locationQuery}
                  onChange={(e) => setLocationQuery(e.target.value)}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter' && businessNameQuery.trim() && !isCheckingReviews) {
                      e.preventDefault();
                      handleSearch();
                    }
                  }}
                  placeholder={detectedLocation ? `${detectedLocation.city}, ${detectedLocation.country}` : "City, Country"}
                  className="w-full pl-9 pr-3 py-2.5 text-gray-900 bg-white border-2 border-gray-200 rounded-lg focus:border-blue-500 focus:ring-2 focus:ring-blue-100 outline-none transition-all text-sm"
                />
              </div>
            </div>

            {/* Validate Button */}
            <button
              onClick={handleSearch}
              disabled={!businessNameQuery.trim() || isCheckingReviews}
              className={`px-5 py-2.5 font-semibold rounded-lg transition-all flex items-center gap-2 whitespace-nowrap ${
                isCheckingReviews
                  ? 'bg-blue-500 text-white cursor-wait'
                  : hasReviews === true && buildSearchQuery() === searchedQuery
                  ? 'bg-green-600 text-white hover:bg-green-700'
                  : hasReviews === false && buildSearchQuery() === searchedQuery
                  ? 'bg-yellow-500 text-white hover:bg-yellow-600'
                  : !businessNameQuery.trim()
                  ? 'bg-gray-300 text-gray-500 cursor-not-allowed'
                  : 'bg-blue-600 text-white hover:bg-blue-700'
              }`}
            >
              {isCheckingReviews ? (
                <>
                  <div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" />
                  <span className="hidden sm:inline">Validating...</span>
                </>
              ) : hasReviews === true && buildSearchQuery() === searchedQuery ? (
                <>
                  <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
                  </svg>
                  <span className="hidden sm:inline">{availableReviewCount?.toLocaleString()} reviews</span>
                  <span className="sm:hidden">{availableReviewCount?.toLocaleString()}</span>
                </>
              ) : hasReviews === false && buildSearchQuery() === searchedQuery ? (
                <>
                  <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
                  </svg>
                  <span className="hidden sm:inline">Not found</span>
                </>
              ) : (
                <>
                  <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
                  </svg>
                  <span className="hidden sm:inline">Validate</span>
                </>
              )}
            </button>
          </div>

          {/* Map Preview Area */}
          <div className="mb-4 rounded-xl overflow-hidden border-2 border-gray-200 bg-gray-100 relative">
            {searchedQuery ? (
              <>
                <iframe
                  src={embedUrl}
                  width="100%"
                  height="300"
                  style={{ border: 0, pointerEvents: 'none' }}
                  allowFullScreen
                  loading="lazy"
                  referrerPolicy="no-referrer-when-downgrade"
                  title="Google Maps Preview"
                />
                {/* Click overlay to prevent iframe interaction */}
                <div
                  className="absolute inset-0 cursor-pointer"
                  onClick={() => setShowMapClickModal(true)}
                />
                {/* Open in Google Maps overlay button */}
                <a
                  href={googleMapsUrl}
                  target="_blank"
                  rel="noopener noreferrer"
                  onClick={(e) => e.stopPropagation()}
                  className="absolute bottom-3 right-3 inline-flex items-center gap-2 px-3 py-1.5 bg-white/90 backdrop-blur border border-gray-300 rounded-lg text-xs font-medium text-gray-700 hover:bg-white hover:border-blue-500 transition-all shadow-md z-10"
                >
                  <svg className="w-3.5 h-3.5" viewBox="0 0 24 24" fill="currentColor">
                    <path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/>
                  </svg>
                  Open in Maps
                  <svg className="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
                  </svg>
                </a>
                {/* Map Click Warning Modal */}
                {showMapClickModal && (
                  <div
                    className="absolute inset-0 flex items-center justify-center backdrop-blur-md bg-gray-900/40 z-20 p-6"
                    onClick={() => setShowMapClickModal(false)}
                  >
                    <div
                      className="bg-white rounded-2xl p-5 shadow-2xl border-2 border-blue-500"
                      style={{ width: '280px' }}
                      onClick={(e) => e.stopPropagation()}
                    >
                      <div className="text-center mb-3">
                        <div className="text-3xl mb-2">🔍</div>
                        <h3 className="text-lg font-bold text-gray-900 mb-1">Use the Search Fields</h3>
                        <p className="text-sm text-gray-600">
                          Please use the fields above to find your business.
                        </p>
                      </div>
                      <div className="bg-blue-50 border border-blue-200 rounded-lg p-2.5 mb-3">
                        <p className="text-xs text-blue-800">
                          <strong>Tip:</strong> Be specific with the name and location.
                        </p>
                      </div>
                      <button
                        onClick={() => {
                          setShowMapClickModal(false);
                          searchInputRef.current?.focus();
                        }}
                        className="w-full py-2.5 bg-blue-600 hover:bg-blue-700 text-white rounded-lg font-semibold transition-all flex items-center justify-center gap-2 text-sm"
                      >
                        <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
                        </svg>
                        Go to Search
                      </button>
                    </div>
                  </div>
                )}
              </>
            ) : (
              <div className="h-[300px] flex items-center justify-center text-gray-400">
                <div className="text-center">
                  <svg className="w-12 h-12 mx-auto mb-3 opacity-50" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
                  </svg>
                  <p>Search for a business to see the map</p>
                </div>
              </div>
            )}
          </div>

          {/* Business Card - Validation Results */}
          {searchedQuery && hasReviews !== null && (
            <div className="mb-6">
              {hasReviews ? (
                // Success - Show Business Card
                <div className="bg-white border-2 border-green-500 rounded-2xl shadow-lg overflow-hidden mb-4">
                  {/* Business Card Layout */}
                  <div className="flex">
                    {/* Business Image */}
                    {businessImage && (
                      <div className="w-40 h-40 flex-shrink-0 bg-gray-200">
                        <img
                          src={businessImage}
                          alt={businessName || 'Business'}
                          className="w-full h-full object-cover"
                          onError={(e) => {
                            // Hide image on error
                            (e.target as HTMLImageElement).style.display = 'none';
                          }}
                        />
                      </div>
                    )}

                    {/* Business Info */}
                    <div className="flex-1 p-5">
                      {/* Category Badge + Verified */}
                      <div className="flex items-center gap-2 mb-2">
                        <span className="inline-flex items-center gap-1 px-2 py-0.5 bg-green-100 text-green-700 text-xs font-semibold rounded-full">
                          <svg className="w-3 h-3" fill="currentColor" viewBox="0 0 20 20">
                            <path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
                          </svg>
                          Verified
                        </span>
                        {businessCategory && (
                          <span className="px-2 py-0.5 bg-gray-100 text-gray-600 text-xs font-medium rounded-full">
                            {businessCategory}
                          </span>
                        )}
                      </div>

                      {/* Business Name */}
                      <h3 className="text-xl font-bold text-gray-900 mb-2 leading-tight">{businessName}</h3>

                      {/* Rating + Reviews Row */}
                      <div className="flex items-center gap-3 mb-2">
                        {businessRating && (
                          <div className="flex items-center gap-1">
                            <span className="text-lg font-bold text-gray-900">{businessRating.toFixed(1)}</span>
                            <div className="flex items-center">
                              {[...Array(5)].map((_, i) => (
                                <svg
                                  key={i}
                                  className={`w-4 h-4 ${i < Math.floor(businessRating) ? 'text-yellow-400' : 'text-gray-300'}`}
                                  fill="currentColor"
                                  viewBox="0 0 20 20"
                                >
                                  <path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
                                </svg>
                              ))}
                            </div>
                          </div>
                        )}
                        {availableReviewCount !== null && availableReviewCount > 0 && (
                          <span className="text-sm text-gray-600 font-medium">
                            ({availableReviewCount.toLocaleString()} reviews)
                          </span>
                        )}
                      </div>

                      {/* Address */}
                      {businessAddress && (
                        <div className="flex items-start gap-1.5 text-gray-500 text-sm">
                          <svg className="w-4 h-4 mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
                            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
                          </svg>
                          <span className="line-clamp-2">{businessAddress}</span>
                        </div>
                      )}
                    </div>
                  </div>

                  {/* Start Scraping Button */}
                  <div className="px-5 pb-5">
                    <form onSubmit={handlePreviewBusiness}>
                      <button
                        type="submit"
                        disabled={isSubmitting}
                        className="w-full py-4 bg-gradient-to-r from-green-600 to-emerald-600 hover:from-green-700 hover:to-emerald-700 text-white rounded-xl font-bold transition-all flex items-center justify-center gap-2 shadow-lg text-lg disabled:opacity-50 disabled:cursor-not-allowed"
                      >
                        {isSubmitting ? (
                          <>
                            <div className="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin" />
                            Starting scrape...
                          </>
                        ) : (
                          <>
                            <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
                            </svg>
                            Scrape {availableReviewCount?.toLocaleString()} Reviews
                          </>
                        )}
                      </button>
                    </form>
                  </div>
                </div>
              ) : (
                // No Reviews - Show Warning
                <div className="p-4 bg-yellow-50 border-2 border-yellow-300 rounded-xl">
                  <div className="flex items-start gap-3">
                    <div className="w-10 h-10 bg-yellow-500 rounded-lg flex items-center justify-center flex-shrink-0">
                      <svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
                      </svg>
                    </div>
                    <div className="flex-1">
                      <p className="font-bold text-yellow-900 text-lg">No reviews available</p>
                      {businessName && (
                        <p className="text-sm text-yellow-800 mt-1">
                          Business: <strong>{businessName}</strong>
                        </p>
                      )}
                      <p className="text-xs text-yellow-700 mt-1">
                        This business has no reviews to scrape. Try a different search.
                      </p>
                    </div>
                  </div>
                </div>
              )}
            </div>
          )}
        </>

      {/* Error */}
      {error && (
        <div className="mb-6 p-4 bg-red-100 border-2 border-red-300 rounded-xl">
          <div className="flex items-start gap-3">
            <svg className="w-6 h-6 text-red-700 flex-shrink-0 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
              <path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clipRule="evenodd" />
            </svg>
            <div>
              <p className="font-bold text-red-900 text-lg">Error</p>
              <p className="text-red-800 mt-1">{error}</p>
            </div>
          </div>
        </div>
      )}

      {/* Jobs List */}
      {jobs.size > 0 && (
        <div className="mb-6 space-y-4">
          <div className="flex items-center justify-between mb-2">
            <h2 className="text-2xl font-bold text-gray-900">
              Scraping Jobs
            </h2>
            <span className="px-3 py-1 bg-blue-100 text-blue-800 font-semibold rounded-full text-sm">
              {jobs.size} {jobs.size === 1 ? 'Job' : 'Jobs'}
            </span>
          </div>

          {Array.from(jobs.values())
            .filter(job => job && job.status)
            .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())
            .map(job => (
            <div
              key={job.job_id}
              className={`p-6 rounded-xl transition-all shadow-md ${
                job.job_id === activeJobId
                  ? 'bg-blue-50 border-2 border-blue-500 shadow-lg'
                  : 'bg-white border-2 border-gray-300'
              }`}
            >
              <div className="flex items-start justify-between mb-4">
                <div className="flex-1">
                  <div className="flex items-center gap-2 mb-3">
                    {getStatusIcon(job.status)}
                    <h3 className="text-lg font-bold text-gray-900">
                      Status: <span className={`${getStatusColor(job.status)} font-extrabold`}>{job.status.toUpperCase()}</span>
                    </h3>
                  </div>
                  <p className="text-xs font-mono text-gray-600 mb-2 bg-gray-100 px-2 py-1 rounded inline-block">{job.job_id}</p>
                  <p className="text-sm text-gray-700 truncate max-w-2xl font-medium">{job.url}</p>
                </div>
                {/* Remove job button */}
                <button
                  onClick={() => removeJob(job.job_id)}
                  className="p-2 text-gray-400 hover:text-red-500 hover:bg-red-50 rounded-lg transition-colors"
                  title="Remove job"
                >
                  <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
                  </svg>
                </button>
              </div>

              {/* Progress Bar for Running Jobs */}
              {job.status === 'running' && job.total_reviews !== null && job.reviews_count !== null && (
                <div className="mb-4 p-4 bg-blue-50 border-2 border-blue-200 rounded-lg">
                  <div className="flex items-center justify-between mb-2">
                    <span className="text-sm font-bold text-blue-900">Extracting Reviews</span>
                    <span className="text-sm font-bold text-blue-700">
                      {job.reviews_count} / {job.total_reviews}
                    </span>
                  </div>
                  <div className="w-full bg-blue-200 rounded-full h-3 overflow-hidden">
                    <div
                      className="bg-gradient-to-r from-blue-500 to-indigo-600 h-3 rounded-full transition-all duration-500 ease-out flex items-center justify-end pr-1"
                      style={{ width: `${Math.min((job.reviews_count / job.total_reviews) * 100, 100)}%` }}
                    >
                      {job.reviews_count > 0 && (
                        <span className="text-xs font-bold text-white drop-shadow">
                          {Math.round((job.reviews_count / job.total_reviews) * 100)}%
                        </span>
                      )}
                    </div>
                  </div>
                </div>
              )}

              <div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-4">
                {job.reviews_count !== null && (
                  <div className="p-4 bg-blue-100 border-2 border-blue-200 rounded-lg">
                    <div className="text-3xl font-bold text-blue-800">{job.reviews_count}</div>
                    <div className="text-xs font-semibold text-blue-700 mt-1">Reviews</div>
                  </div>
                )}
                {job.scrape_time !== null && (
                  <div className="p-4 bg-green-100 border-2 border-green-200 rounded-lg">
                    <div className="text-3xl font-bold text-green-800">{job.scrape_time.toFixed(1)}s</div>
                    <div className="text-xs font-semibold text-green-700 mt-1">Time</div>
                  </div>
                )}
                {job.scrape_time && job.reviews_count && (
                  <div className="p-4 bg-purple-100 border-2 border-purple-200 rounded-lg">
                    <div className="text-3xl font-bold text-purple-800">
                      {(job.reviews_count / job.scrape_time).toFixed(1)}
                    </div>
                    <div className="text-xs font-semibold text-purple-700 mt-1">Reviews/sec</div>
                  </div>
                )}
                {job.started_at && (
                  <div className="p-4 bg-gray-100 border-2 border-gray-300 rounded-lg">
                    <div className="text-lg font-bold text-gray-800">
                      {new Date(job.started_at).toLocaleTimeString()}
                    </div>
                    <div className="text-xs font-semibold text-gray-700 mt-1">Started</div>
                  </div>
                )}
                {job.status === 'running' && job.updated_at && (
                  <div className="p-4 bg-blue-100 border-2 border-blue-200 rounded-lg">
                    <div className="text-lg font-bold text-blue-800">
                      {new Date(job.updated_at).toLocaleTimeString()}
                    </div>
                    <div className="text-xs font-semibold text-blue-700 mt-1">Last Update</div>
                  </div>
                )}
              </div>

              {/* Action Buttons - Show when completed, partial, or running with reviews */}
              {(job.status === 'completed' || job.status === 'partial' || (job.status === 'running' && job.reviews_count && job.reviews_count > 0)) && job.reviews_count && job.reviews_count > 0 && (
                <div className="flex gap-3">
                  <button
                    onClick={async () => {
                      setError('');
                      setIsLoadingReviews(true);

                      try {
                        console.log('Fetching reviews for job:', job.job_id);
                        const reviewsResponse = await fetch(`/api/jobs/${job.job_id}/reviews?limit=10000`);

                        if (!reviewsResponse.ok) {
                          throw new Error(`Failed to fetch reviews: ${reviewsResponse.status}`);
                        }

                        const reviewsData = await reviewsResponse.json();
                        console.log('Reviews fetched:', reviewsData);

                        if (!reviewsData.reviews || reviewsData.reviews.length === 0) {
                          setError('No reviews found for this job');
                          setIsLoadingReviews(false);
                          return;
                        }

                        setReviews(reviewsData.reviews);
                        setActiveJobId(job.job_id);

                        // Call parent callback if provided (for right panel display)
                        if (onSelectReviews) {
                          onSelectReviews(reviewsData.reviews, searchedQuery || 'Business', job.job_id);
                        } else {
                          setShowAnalytics(true);
                        }
                      } catch (err) {
                        console.error('Failed to fetch reviews:', err);
                        setError(err instanceof Error ? err.message : 'Failed to load reviews for analysis');
                      } finally {
                        setIsLoadingReviews(false);
                      }
                    }}
                    disabled={isLoadingReviews}
                    className={`flex-1 py-4 text-white rounded-xl font-bold transition-all flex items-center justify-center gap-2 shadow-lg disabled:opacity-50 disabled:cursor-not-allowed text-lg border-2 ${
                      job.status === 'partial'
                        ? 'bg-gradient-to-r from-orange-500 to-amber-600 hover:from-orange-600 hover:to-amber-700 border-orange-400'
                        : job.status === 'running'
                        ? 'bg-gradient-to-r from-blue-500 to-cyan-600 hover:from-blue-600 hover:to-cyan-700 border-blue-400'
                        : 'bg-gradient-to-r from-blue-600 to-indigo-700 hover:from-blue-700 hover:to-indigo-800 border-blue-500'
                    }`}
                  >
                    {isLoadingReviews ? (
                      <>
                        <div className="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin" />
                        Loading Reviews...
                      </>
                    ) : (
                      <>
                        <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
                        </svg>
                        📊 {job.status === 'running' ? 'Preview Analytics' : job.status === 'partial' ? 'View Partial Data' : 'Open Analytics Dashboard'}
                      </>
                    )}
                  </button>
                  <button
                    onClick={async () => {
                      try {
                        const reviewsResponse = await fetch(`/api/jobs/${job.job_id}/reviews?limit=10000`);
                        if (reviewsResponse.ok) {
                          const reviewsData = await reviewsResponse.json();
                          const data = JSON.stringify(reviewsData.reviews, null, 2);
                          const blob = new Blob([data], { type: 'application/json' });
                          const url = URL.createObjectURL(blob);
                          const a = document.createElement('a');
                          a.href = url;
                          a.download = `reviews-${job.job_id}${job.status === 'partial' ? '-partial' : ''}.json`;
                          a.click();
                        }
                      } catch (err) {
                        console.error('Failed to export reviews:', err);
                      }
                    }}
                    className="px-6 py-4 bg-gray-700 hover:bg-gray-800 text-white border-2 border-gray-600 rounded-xl font-bold transition-colors flex items-center justify-center gap-2 shadow-md"
                  >
                    <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
                    </svg>
                    Export JSON
                  </button>
                </div>
              )}

              {/* Partial Job Warning */}
              {job.status === 'partial' && (
                <div className="mt-4 p-4 bg-orange-100 border-2 border-orange-300 rounded-lg">
                  <div className="flex items-start gap-2">
                    <svg className="w-5 h-5 text-orange-700 flex-shrink-0 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
                      <path fillRule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clipRule="evenodd" />
                    </svg>
                    <div>
                      <p className="font-bold text-orange-900">Partial Results</p>
                      <p className="text-sm text-orange-800 mt-1">
                        This job was interrupted but {job.reviews_count} reviews were saved.
                        {job.error_message && <span className="block mt-1 text-orange-700">Reason: {job.error_message}</span>}
                      </p>
                    </div>
                  </div>
                </div>
              )}

              {/* Error Message */}
              {job.status === 'failed' && job.error_message && (
                <div className="mt-4 p-4 bg-red-100 border-2 border-red-300 rounded-lg">
                  <div className="flex items-start gap-2">
                    <svg className="w-5 h-5 text-red-700 flex-shrink-0 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
                      <path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clipRule="evenodd" />
                    </svg>
                    <div>
                      <p className="font-bold text-red-900">Error</p>
                      <p className="text-sm text-red-800 mt-1">{job.error_message}</p>
                    </div>
                  </div>
                </div>
              )}
            </div>
          ))}
        </div>
      )}

      {/* Analytics Dashboard or Simple Review List */}
      {reviews.length > 0 && (
        <>
          {showAnalytics ? (
            <div>
              <div className="mb-4">
                <button
                  onClick={() => setShowAnalytics(false)}
                  className="flex items-center gap-2 text-blue-600 hover:text-blue-700 font-medium"
                >
                  <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
                  </svg>
                  Back to Simple View
                </button>
              </div>
              <ReviewAnalytics reviews={reviews} businessName={searchedQuery || 'Business'} />
            </div>
          ) : (
            <div>
              <div className="flex items-center justify-between mb-4">
                <h3 className="text-xl font-bold text-gray-900">
                  Reviews ({reviews.length})
                </h3>
                <button
                  onClick={() => {
                    const data = JSON.stringify(reviews, null, 2);
                    const blob = new Blob([data], { type: 'application/json' });
                    const url = URL.createObjectURL(blob);
                    const a = document.createElement('a');
                    a.href = url;
                    a.download = `reviews-${activeJobId || 'export'}.json`;
                    a.click();
                  }}
                  className="px-4 py-2 text-sm bg-gray-700 hover:bg-gray-800 text-white border-2 border-gray-600 rounded-lg font-bold transition-colors shadow-md"
                >
                  Export JSON
                </button>
              </div>

              <div className="space-y-3 max-h-[600px] overflow-y-auto pr-2">
                {reviews.map((review, index) => (
                  <div key={`${index}-${review.review_id}`} className="p-4 bg-white border border-gray-200 rounded-xl hover:border-gray-300 transition-colors">
                    <div className="flex items-start gap-3">
                      {review.avatar_url && (
                        <img
                          src={review.avatar_url}
                          alt={review.author}
                          className="w-10 h-10 rounded-full"
                        />
                      )}
                      <div className="flex-1 min-w-0">
                        <div className="flex items-center justify-between mb-1">
                          <span className="font-medium text-gray-900">{review.author}</span>
                          <div className="flex items-center gap-1">
                            {[...Array(5)].map((_, i) => (
                              <svg
                                key={i}
                                className={`w-4 h-4 ${i < review.rating ? 'text-yellow-400' : 'text-gray-300'}`}
                                fill="currentColor"
                                viewBox="0 0 20 20"
                              >
                                <path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
                              </svg>
                            ))}
                          </div>
                        </div>
                        <p className="text-xs text-gray-500 mb-2">{review.date_text}</p>
                        {review.text && (
                          <p className="text-sm text-gray-700 leading-relaxed">{review.text}</p>
                        )}
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            </div>
          )}
        </>
      )}

      {/* Confirmation Modal - rendered via portal to modal-root for proper centering */}
      {showConfirmModal && typeof document !== 'undefined' && document.getElementById('modal-root') && createPortal(
        <div
          className="fixed inset-0 z-50 bg-black/50 backdrop-blur-sm flex items-center justify-center p-4"
          onClick={() => setShowConfirmModal(false)}
        >
          <div
            className="bg-white rounded-2xl shadow-2xl border-2 border-green-500 animate-fade-in w-full max-w-[400px]"
            onClick={(e) => e.stopPropagation()}
          >
            {/* Header */}
            <div className="bg-gradient-to-r from-green-600 to-emerald-600 text-white px-6 py-5 rounded-t-xl">
              <div className="flex items-center gap-3">
                <div className="w-10 h-10 bg-white/20 rounded-lg flex items-center justify-center">
                  <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
                  </svg>
                </div>
                <h2 className="text-xl font-bold">Start Scraping?</h2>
              </div>
            </div>

            {/* Content */}
            <div className="px-6 py-5">
              <p className="text-gray-700 mb-4">
                This will start scraping reviews for:
              </p>
              <div className="bg-green-50 border-2 border-green-200 rounded-lg p-4 mb-4">
                <p className="font-bold text-green-900 text-lg">{businessName}</p>
                {businessAddress && (
                  <p className="text-sm text-green-700 mt-1">{businessAddress}</p>
                )}
              </div>

              {/* Scraper Version Selector */}
              <div className="mb-4">
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  Scraper Version
                </label>
                <select
                  value={scraperVersion}
                  onChange={(e) => setScraperVersion(e.target.value)}
                  className="w-full px-3 py-2 border-2 border-gray-200 rounded-lg focus:border-green-500 focus:ring-2 focus:ring-green-200 transition-all bg-white text-gray-900 font-medium"
                >
                  {AVAILABLE_VERSIONS.map((v) => (
                    <option key={v.value} value={v.value} className="text-gray-900">
                      {v.label} - {v.description}
                    </option>
                  ))}
                </select>
                <p className="mt-1 text-xs text-gray-500">
                  {scraperVersion === '1.1.0'
                    ? '✨ Multi-sort enabled: Can collect more than 1000 reviews'
                    : 'Standard scraping (up to ~1000 reviews)'}
                </p>
              </div>

              <p className="text-sm text-gray-600">
                The scraping job will run in the background. You can monitor progress below.
              </p>
            </div>

            {/* Actions */}
            <div className="px-6 py-4 bg-gray-50 rounded-b-xl border-t-2 border-gray-200 flex gap-3">
              <button
                onClick={() => setShowConfirmModal(false)}
                className="flex-1 py-3 px-4 bg-gray-200 hover:bg-gray-300 text-gray-800 rounded-lg font-semibold transition-all"
              >
                Cancel
              </button>
              <button
                onClick={handleConfirmScrape}
                disabled={isSubmitting}
                className="flex-1 py-3 px-4 bg-gradient-to-r from-green-600 to-emerald-600 hover:from-green-700 hover:to-emerald-700 text-white rounded-lg font-semibold transition-all flex items-center justify-center gap-2 disabled:opacity-50"
              >
                {isSubmitting ? (
                  <>
                    <div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" />
                    Starting...
                  </>
                ) : (
                  <>
                    <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
                    </svg>
                    Confirm
                  </>
                )}
              </button>
            </div>
          </div>
        </div>,
        document.getElementById('modal-root')!
      )}
    </div>
  );
}
