'use client';

import React, { useState, useMemo, useEffect, useCallback } from 'react';
import Link from 'next/link';
import {
  useReactTable,
  getCoreRowModel,
  getFilteredRowModel,
  getSortedRowModel,
  getPaginationRowModel,
  ColumnDef,
  flexRender,
  SortingState,
  ColumnFiltersState,
} from '@tanstack/react-table';
import { JobStatus } from './ScraperTest';

interface LogEntry {
  timestamp: string;
  level: string;
  message: string;
  source: string;
}

interface JobLogs {
  job_id: string;
  status: string;
  error_message: string | null;
  logs: LogEntry[];
  log_count: number;
}

interface JobsViewProps {
  jobs: JobStatus[];
  onSelectJob: (job: JobStatus, previousJob?: JobStatus) => void;
  isLoadingJob: string | null;
  onRefresh?: () => void;
}

// Helper to format duration
function formatDuration(seconds: number): string {
  if (seconds < 60) return `${seconds.toFixed(1)}s`;
  const mins = Math.floor(seconds / 60);
  const secs = Math.round(seconds % 60);
  return `${mins}m ${secs}s`;
}

// Helper to calculate speed (reviews/second)
function calculateSpeed(reviewCount: number | null, scrapeTime: number | null): number | null {
  if (!reviewCount || !scrapeTime || scrapeTime === 0) return null;
  return reviewCount / scrapeTime;
}

// Helper to extract business name from URL
function extractBusinessName(job: JobStatus): string {
  if (job.business_name) return job.business_name;
  try {
    const urlObj = new URL(job.url);
    const query = urlObj.searchParams.get('query');
    return query ? decodeURIComponent(query) : 'Unknown Business';
  } catch {
    return 'Unknown Business';
  }
}

export default function JobsView({ jobs, onSelectJob, isLoadingJob, onRefresh }: JobsViewProps) {
  const [sorting, setSorting] = useState<SortingState>([{ id: 'created_at', desc: true }]);
  const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
  const [globalFilter, setGlobalFilter] = useState('');
  const [statusFilter, setStatusFilter] = useState<string>('all');
  const [selectedJobLogs, setSelectedJobLogs] = useState<JobLogs | null>(null);
  const [loadingLogs, setLoadingLogs] = useState<string | null>(null);
  const [expandedErrors, setExpandedErrors] = useState<Set<string>>(new Set());

  // Live monitoring state
  const [monitoredJob, setMonitoredJob] = useState<JobStatus | null>(null);
  const [monitoredJobLogs, setMonitoredJobLogs] = useState<LogEntry[]>([]);
  const [isMonitoring, setIsMonitoring] = useState(false);

  // Delete state
  const [deleteConfirm, setDeleteConfirm] = useState<JobStatus | null>(null);
  const [isDeleting, setIsDeleting] = useState<string | null>(null);
  const [bulkDeleteConfirm, setBulkDeleteConfirm] = useState<'all' | 'completed' | 'failed' | null>(null);
  const [isBulkDeleting, setIsBulkDeleting] = useState(false);

  // Real-time updates for running jobs in the table
  const [runningJobUpdates, setRunningJobUpdates] = useState<Map<string, JobStatus>>(new Map());

  // SSE connection for real-time job updates
  useEffect(() => {
    const hasRunningJobs = jobs.some(j => j.status === 'running');

    // Only connect to SSE if there are running jobs
    if (!hasRunningJobs) {
      setRunningJobUpdates(new Map());
      return;
    }

    let eventSource: EventSource | null = null;
    let reconnectTimeout: NodeJS.Timeout | null = null;

    const connect = () => {
      eventSource = new EventSource('/api/jobs/stream');

      eventSource.onopen = () => {
        console.log('SSE connected for job updates');
      };

      eventSource.addEventListener('job_progress', (event) => {
        try {
          const data = JSON.parse(event.data);
          setRunningJobUpdates(prev => {
            const updated = new Map(prev);
            updated.set(data.job_id, {
              job_id: data.job_id,
              status: 'running',
              reviews_count: data.reviews_count,
              total_reviews: data.total_reviews,
              scrape_time: data.scrape_time,
            } as JobStatus);
            return updated;
          });
        } catch (err) {
          console.error('Failed to parse job_progress event:', err);
        }
      });

      eventSource.addEventListener('job_completed', (event) => {
        try {
          const data = JSON.parse(event.data);
          // Remove from running updates and trigger refresh
          setRunningJobUpdates(prev => {
            const updated = new Map(prev);
            updated.delete(data.job_id);
            return updated;
          });
          // Refresh the jobs list to get final state
          onRefresh?.();
        } catch (err) {
          console.error('Failed to parse job_completed event:', err);
        }
      });

      eventSource.addEventListener('job_failed', (event) => {
        try {
          const data = JSON.parse(event.data);
          setRunningJobUpdates(prev => {
            const updated = new Map(prev);
            updated.delete(data.job_id);
            return updated;
          });
          onRefresh?.();
        } catch (err) {
          console.error('Failed to parse job_failed event:', err);
        }
      });

      eventSource.addEventListener('job_partial', (event) => {
        try {
          const data = JSON.parse(event.data);
          setRunningJobUpdates(prev => {
            const updated = new Map(prev);
            updated.delete(data.job_id);
            return updated;
          });
          onRefresh?.();
        } catch (err) {
          console.error('Failed to parse job_partial event:', err);
        }
      });

      eventSource.onerror = () => {
        console.log('SSE connection error, reconnecting...');
        eventSource?.close();
        // Reconnect after 3 seconds
        reconnectTimeout = setTimeout(connect, 3000);
      };
    };

    connect();

    return () => {
      eventSource?.close();
      if (reconnectTimeout) clearTimeout(reconnectTimeout);
    };
  }, [jobs, onRefresh]);

  // Merge jobs with real-time updates
  const jobsWithUpdates = useMemo(() => {
    return jobs.map(job => {
      const update = runningJobUpdates.get(job.job_id);
      if (update && job.status === 'running') {
        return { ...job, ...update };
      }
      return job;
    });
  }, [jobs, runningJobUpdates]);

  const fetchJobLogs = async (jobId: string) => {
    setLoadingLogs(jobId);
    try {
      const response = await fetch(`/api/jobs/${jobId}/logs`);
      if (response.ok) {
        const data = await response.json();
        setSelectedJobLogs(data);
      }
    } catch (err) {
      console.error('Failed to fetch logs:', err);
    } finally {
      setLoadingLogs(null);
    }
  };

  // Generate crash report for a job
  const [copyingCrashReport, setCopyingCrashReport] = useState<string | null>(null);

  const generateCrashReport = async (job: JobStatus): Promise<string> => {
    // Fetch logs for the job
    let logs: LogEntry[] = [];
    let logCount = 0;
    try {
      const response = await fetch(`/api/jobs/${job.job_id}/logs`);
      if (response.ok) {
        const data = await response.json();
        logs = data.logs || [];
        logCount = data.log_count || 0;
      }
    } catch (err) {
      console.error('Failed to fetch logs for crash report:', err);
    }

    const businessName = extractBusinessName(job);
    const now = new Date().toISOString();

    // Format logs (last 50 entries)
    const recentLogs = [...logs]
      .sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())
      .slice(0, 50)
      .reverse();

    const logsFormatted = recentLogs.length > 0
      ? recentLogs.map(log =>
          `[${new Date(log.timestamp).toISOString()}] [${log.level.toUpperCase()}] [${log.source}] ${log.message}`
        ).join('\n')
      : 'No logs available';

    // Calculate duration
    const duration = job.scrape_time
      ? formatDuration(job.scrape_time)
      : job.started_at
        ? formatDuration((Date.now() - new Date(job.started_at).getTime()) / 1000)
        : 'Unknown';

    // Build the crash report
    const report = `## Crash Report: ${job.job_id}

**Generated**: ${now}
**Status**: ${job.status.toUpperCase()}
**Job Type**: google-reviews

### Business Info
- **Name**: ${businessName}
- **Address**: ${job.business_address || 'N/A'}
- **Category**: ${job.business_category || 'N/A'}
- **URL**: ${job.url}

### Job Timeline
- **Created**: ${job.created_at}
- **Started**: ${job.started_at || 'N/A'}
- **Completed**: ${job.completed_at || 'N/A'}
- **Last Update**: ${job.updated_at || 'N/A'}
- **Duration**: ${duration}

### Progress at Failure
- **Reviews Collected**: ${job.reviews_count ?? 0}${job.total_reviews ? ` / ${job.total_reviews}` : ''}
- **Expected Total**: ${job.total_reviews_snapshot ?? 'Unknown'}
- **Rating Snapshot**: ${job.rating_snapshot ?? 'N/A'}

### Error
\`\`\`
${job.error_message || 'No error message captured'}
\`\`\`

### Logs (${logCount} total, showing last ${recentLogs.length})
\`\`\`
${logsFormatted}
\`\`\`

### Context for Debugging
- This is a Google Reviews scraper job
- The scraper uses Playwright to navigate Google Maps
- Reviews are extracted by scrolling through the reviews panel
- Common failure points: rate limiting, DOM structure changes, network timeouts

### Suggested Investigation
1. Check if error is related to rate limiting (look for 429 or "too many requests")
2. Check if DOM selectors have changed (look for "element not found" errors)
3. Check network/timeout issues (look for "timeout" or "navigation" errors)
4. Review the last few log entries before the error for context
`;

    return report;
  };

  const copyCrashReport = async (job: JobStatus) => {
    setCopyingCrashReport(job.job_id);
    try {
      const report = await generateCrashReport(job);
      await navigator.clipboard.writeText(report);
      // Brief visual feedback
      setTimeout(() => setCopyingCrashReport(null), 1500);
    } catch (err) {
      console.error('Failed to copy crash report:', err);
      setCopyingCrashReport(null);
    }
  };

  // Live monitoring functions
  const startMonitoring = useCallback((job: JobStatus) => {
    setMonitoredJob(job);
    setMonitoredJobLogs([]);
    setIsMonitoring(true);
  }, []);

  const stopMonitoring = useCallback(() => {
    setIsMonitoring(false);
    setMonitoredJob(null);
    setMonitoredJobLogs([]);
  }, []);

  // Delete a single job
  const deleteJob = useCallback(async (jobId: string) => {
    setIsDeleting(jobId);
    try {
      const response = await fetch(`/api/jobs/${jobId}`, { method: 'DELETE' });
      if (response.ok) {
        setDeleteConfirm(null);
        onRefresh?.();
      } else {
        console.error('Failed to delete job');
      }
    } catch (err) {
      console.error('Error deleting job:', err);
    } finally {
      setIsDeleting(null);
    }
  }, [onRefresh]);

  // Bulk delete jobs by status
  const bulkDeleteJobs = useCallback(async (status: 'all' | 'completed' | 'failed') => {
    setIsBulkDeleting(true);
    try {
      const jobsToDelete = status === 'all'
        ? jobs
        : jobs.filter(j => j.status === status);

      await Promise.all(
        jobsToDelete.map(job =>
          fetch(`/api/jobs/${job.job_id}`, { method: 'DELETE' })
        )
      );

      setBulkDeleteConfirm(null);
      onRefresh?.();
    } catch (err) {
      console.error('Error bulk deleting jobs:', err);
    } finally {
      setIsBulkDeleting(false);
    }
  }, [jobs, onRefresh]);

  // SSE connection for live monitoring
  useEffect(() => {
    if (!isMonitoring || !monitoredJob) return;

    let eventSource: EventSource | null = null;
    let reconnectTimeout: NodeJS.Timeout | null = null;

    const connect = () => {
      eventSource = new EventSource(`/api/jobs/${monitoredJob.job_id}/stream`);

      eventSource.onopen = () => {
        console.log('SSE connected for live monitoring');
      };

      eventSource.addEventListener('initial_state', (event) => {
        try {
          const data = JSON.parse(event.data);
          setMonitoredJob(prev => prev ? { ...prev, ...data } : prev);
          if (data.logs) {
            setMonitoredJobLogs(data.logs);
          }
        } catch (err) {
          console.error('Failed to parse initial_state event:', err);
        }
      });

      eventSource.addEventListener('job_progress', (event) => {
        try {
          const data = JSON.parse(event.data);
          setMonitoredJob(prev => prev ? {
            ...prev,
            status: 'running',
            reviews_count: data.reviews_count,
            total_reviews: data.total_reviews,
            scrape_time: data.scrape_time,
          } : prev);
          if (data.logs) {
            setMonitoredJobLogs(data.logs);
          }
        } catch (err) {
          console.error('Failed to parse job_progress event:', err);
        }
      });

      eventSource.addEventListener('job_completed', (event) => {
        try {
          const data = JSON.parse(event.data);
          setMonitoredJob(prev => prev ? {
            ...prev,
            status: 'completed',
            reviews_count: data.reviews_count,
            total_reviews: data.total_reviews,
            scrape_time: data.scrape_time,
          } : prev);
          if (data.logs) {
            setMonitoredJobLogs(data.logs);
          }
          // Stop monitoring but keep modal open
          setIsMonitoring(false);
          eventSource?.close();
        } catch (err) {
          console.error('Failed to parse job_completed event:', err);
        }
      });

      eventSource.addEventListener('job_failed', (event) => {
        try {
          const data = JSON.parse(event.data);
          setMonitoredJob(prev => prev ? {
            ...prev,
            status: 'failed',
            error_message: data.error,
          } : prev);
          if (data.logs) {
            setMonitoredJobLogs(data.logs);
          }
          setIsMonitoring(false);
          eventSource?.close();
        } catch (err) {
          console.error('Failed to parse job_failed event:', err);
        }
      });

      eventSource.addEventListener('job_update', (event) => {
        try {
          const data = JSON.parse(event.data);
          setMonitoredJob(prev => prev ? { ...prev, ...data } : prev);
          if (data.logs) {
            setMonitoredJobLogs(data.logs);
          }
          // Check if job is no longer running
          if (data.status && data.status !== 'running') {
            setIsMonitoring(false);
            eventSource?.close();
          }
        } catch (err) {
          console.error('Failed to parse job_update event:', err);
        }
      });

      eventSource.onerror = () => {
        console.log('SSE connection error for live monitor, reconnecting...');
        eventSource?.close();
        // Reconnect after 2 seconds
        reconnectTimeout = setTimeout(connect, 2000);
      };
    };

    connect();

    return () => {
      eventSource?.close();
      if (reconnectTimeout) clearTimeout(reconnectTimeout);
    };
  }, [isMonitoring, monitoredJob?.job_id]);

  // Calculate summary stats
  const stats = useMemo(() => {
    const completed = jobsWithUpdates.filter(j => j.status === 'completed');
    const failed = jobsWithUpdates.filter(j => j.status === 'failed');
    const running = jobsWithUpdates.filter(j => j.status === 'running');

    const totalReviews = completed.reduce((sum, j) => sum + (j.reviews_count || 0), 0);
    const totalTime = completed.reduce((sum, j) => sum + (j.scrape_time || 0), 0);
    const avgTime = completed.length > 0 ? totalTime / completed.length : 0;
    const successRate = jobsWithUpdates.length > 0 ? (completed.length / jobsWithUpdates.length) * 100 : 0;

    // Jobs today
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    const jobsToday = jobsWithUpdates.filter(j => new Date(j.created_at) >= today).length;

    // Average speed
    const speeds = completed
      .map(j => calculateSpeed(j.reviews_count, j.scrape_time))
      .filter((s): s is number => s !== null);
    const avgSpeed = speeds.length > 0 ? speeds.reduce((a, b) => a + b, 0) / speeds.length : 0;

    return {
      total: jobsWithUpdates.length,
      completed: completed.length,
      failed: failed.length,
      running: running.length,
      totalReviews,
      avgTime,
      successRate,
      jobsToday,
      avgSpeed,
    };
  }, [jobsWithUpdates]);

  // Filter jobs by status
  const filteredJobs = useMemo(() => {
    if (statusFilter === 'all') return jobsWithUpdates;
    return jobsWithUpdates.filter(j => j.status === statusFilter);
  }, [jobsWithUpdates, statusFilter]);

  // Find previous job for comparison
  const findPreviousJob = (job: JobStatus): JobStatus | undefined => {
    const sameBusinessJobs = jobsWithUpdates
      .filter(j => {
        const jobBusiness = extractBusinessName(j);
        const currentBusiness = extractBusinessName(job);
        return jobBusiness === currentBusiness && j.job_id !== job.job_id;
      })
      .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());

    const jobDate = new Date(job.created_at);
    return sameBusinessJobs.find(j =>
      new Date(j.created_at) < jobDate &&
      j.status === 'completed' &&
      j.reviews_count
    );
  };

  // Table columns
  const columns = useMemo<ColumnDef<JobStatus>[]>(
    () => [
      {
        accessorKey: 'business',
        header: ({ column }) => (
          <button
            onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
            className="flex items-center gap-2 hover:text-blue-700 font-semibold"
          >
            Business
            <SortIcon sorted={column.getIsSorted()} />
          </button>
        ),
        accessorFn: (row) => extractBusinessName(row),
        cell: ({ row }) => {
          const name = extractBusinessName(row.original);
          const address = row.original.business_address;
          return (
            <div className="max-w-xs">
              <div className="font-semibold text-gray-900 truncate" title={name}>
                {name}
              </div>
              {address && (
                <div className="text-xs text-gray-500 truncate" title={address}>
                  {address}
                </div>
              )}
            </div>
          );
        },
      },
      {
        id: 'url',
        header: 'URL',
        cell: ({ row }) => {
          const url = row.original.url;
          return (
            <a
              href={url}
              target="_blank"
              rel="noopener noreferrer"
              onClick={(e) => e.stopPropagation()}
              className="inline-flex items-center gap-1.5 px-2.5 py-1.5 bg-gray-100 hover:bg-gray-200 text-gray-700 text-xs font-medium rounded-lg transition-colors"
              title={url}
            >
              <svg className="w-3.5 h-3.5" 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>
              Open
            </a>
          );
        },
      },
      {
        accessorKey: 'status',
        header: ({ column }) => (
          <button
            onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
            className="flex items-center gap-2 hover:text-blue-700 font-semibold"
          >
            Status
            <SortIcon sorted={column.getIsSorted()} />
          </button>
        ),
        cell: ({ row }) => {
          const status = row.original.status;
          const isStuck = status === 'running' &&
            new Date().getTime() - new Date(row.original.created_at).getTime() > 10 * 60 * 1000;

          return (
            <div className="flex items-center gap-2">
              <span className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-semibold ${
                status === 'completed' ? 'bg-green-100 text-green-800' :
                status === 'partial' ? 'bg-orange-100 text-orange-800' :
                isStuck ? 'bg-red-100 text-red-800' :
                status === 'running' ? 'bg-blue-100 text-blue-800' :
                status === 'failed' ? 'bg-red-100 text-red-800' :
                'bg-gray-100 text-gray-800'
              }`}>
                {status === 'running' && !isStuck && (
                  <div className="w-2 h-2 border border-current border-t-transparent rounded-full animate-spin" />
                )}
                {status === 'partial' && (
                  <svg className="w-3 h-3" 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>
                )}
                {isStuck && (
                  <svg className="w-3 h-3" 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>
                )}
                {isStuck ? 'Stuck' : status ? status.charAt(0).toUpperCase() + status.slice(1) : 'Unknown'}
              </span>
            </div>
          );
        },
      },
      {
        accessorKey: 'reviews_count',
        header: ({ column }) => (
          <button
            onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
            className="flex items-center gap-2 hover:text-blue-700 font-semibold"
          >
            Reviews
            <SortIcon sorted={column.getIsSorted()} />
          </button>
        ),
        cell: ({ row }) => {
          const count = row.original.reviews_count;
          const total = row.original.total_reviews;

          if (count === null) return <span className="text-gray-400">-</span>;

          const coverage = total ? Math.round((count / total) * 100) : null;

          return (
            <div>
              <div className="font-semibold text-gray-900">
                {count.toLocaleString()}
                {total && total !== count && (
                  <span className="text-gray-500 font-normal"> / {total.toLocaleString()}</span>
                )}
              </div>
              {coverage !== null && coverage < 100 && (
                <div className="mt-1">
                  <div className="w-16 h-1.5 bg-gray-200 rounded-full overflow-hidden">
                    <div
                      className="h-full bg-blue-500 rounded-full"
                      style={{ width: `${coverage}%` }}
                    />
                  </div>
                </div>
              )}
            </div>
          );
        },
      },
      {
        accessorKey: 'scrape_time',
        header: ({ column }) => (
          <button
            onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
            className="flex items-center gap-2 hover:text-blue-700 font-semibold"
          >
            Duration
            <SortIcon sorted={column.getIsSorted()} />
          </button>
        ),
        cell: ({ row }) => {
          const job = row.original;
          const isRunning = job.status === 'running';
          const isPartial = job.status === 'partial';
          const isStuck = isRunning &&
            new Date().getTime() - new Date(job.created_at).getTime() > 10 * 60 * 1000;

          // For actively running jobs (not stuck), show live elapsed time
          if (isRunning && !isStuck && job.started_at) {
            const elapsed = (Date.now() - new Date(job.started_at).getTime()) / 1000;
            return (
              <span className="font-medium text-blue-600 flex items-center gap-1">
                <div className="w-2 h-2 bg-blue-500 rounded-full animate-pulse" />
                {formatDuration(elapsed)}
              </span>
            );
          }

          // For stuck jobs, show frozen elapsed time in red (no pulse)
          if (isStuck && job.started_at) {
            const elapsed = (Date.now() - new Date(job.started_at).getTime()) / 1000;
            return (
              <span className="font-medium text-red-600">
                {formatDuration(elapsed)}
              </span>
            );
          }

          // For partial jobs, use scrape_time or calculate from timestamps
          if (isPartial) {
            const time = job.scrape_time;
            if (time !== null) {
              return (
                <span className="font-medium text-orange-600">
                  {formatDuration(time)}
                </span>
              );
            }
            // Fallback: calculate from started_at to completed_at
            if (job.started_at && job.completed_at) {
              const elapsed = (new Date(job.completed_at).getTime() - new Date(job.started_at).getTime()) / 1000;
              return (
                <span className="font-medium text-orange-600">
                  {formatDuration(elapsed)}
                </span>
              );
            }
          }

          const time = job.scrape_time;
          if (time === null) return <span className="text-gray-400">-</span>;

          return (
            <span className="font-medium text-gray-700">
              {formatDuration(time)}
            </span>
          );
        },
      },
      {
        id: 'speed',
        header: ({ column }) => (
          <button
            onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
            className="flex items-center gap-2 hover:text-blue-700 font-semibold"
          >
            Speed
            <SortIcon sorted={column.getIsSorted()} />
          </button>
        ),
        accessorFn: (row) => {
          const isStuck = row.status === 'running' &&
            new Date().getTime() - new Date(row.created_at).getTime() > 10 * 60 * 1000;

          // For actively running jobs (not stuck), calculate speed from last successful data retrieval
          if (row.status === 'running' && !isStuck && row.started_at && row.reviews_count) {
            // Use updated_at (last successful data loop) if available, otherwise fall back to Date.now()
            const endTime = row.updated_at ? new Date(row.updated_at).getTime() : Date.now();
            const elapsed = (endTime - new Date(row.started_at).getTime()) / 1000;
            return elapsed > 0 ? row.reviews_count / elapsed : null;
          }
          return calculateSpeed(row.reviews_count, row.scrape_time);
        },
        cell: ({ row }) => {
          const job = row.original;
          const isRunning = job.status === 'running';
          const isPartial = job.status === 'partial';
          const isStuck = isRunning &&
            new Date().getTime() - new Date(job.created_at).getTime() > 10 * 60 * 1000;

          // For actively running jobs (not stuck), show live speed based on last successful data retrieval
          if (isRunning && !isStuck && job.started_at && job.reviews_count) {
            // Use updated_at (last successful data loop) if available, otherwise fall back to Date.now()
            const endTime = job.updated_at ? new Date(job.updated_at).getTime() : Date.now();
            const elapsed = (endTime - new Date(job.started_at).getTime()) / 1000;
            const speed = elapsed > 0 ? job.reviews_count / elapsed : 0;
            const isGood = speed >= 1;
            const isSlow = speed < 0.5;

            return (
              <span className={`font-medium flex items-center gap-1 ${
                isGood ? 'text-green-600' : isSlow ? 'text-orange-500' : 'text-blue-600'
              }`}>
                <div className="w-2 h-2 bg-current rounded-full animate-pulse" />
                {speed.toFixed(1)}/s
              </span>
            );
          }

          // For stuck jobs, show frozen speed in red (use updated_at for accurate speed)
          if (isStuck && job.started_at && job.reviews_count) {
            const endTime = job.updated_at ? new Date(job.updated_at).getTime() : Date.now();
            const elapsed = (endTime - new Date(job.started_at).getTime()) / 1000;
            const speed = elapsed > 0 ? job.reviews_count / elapsed : 0;
            return (
              <span className="font-medium text-red-600">
                {speed.toFixed(1)}/s
              </span>
            );
          }

          // For partial jobs, show speed in orange
          if (isPartial) {
            const speed = calculateSpeed(job.reviews_count, job.scrape_time);
            if (speed !== null) {
              return (
                <span className="font-medium text-orange-600">
                  {speed.toFixed(1)}/s
                </span>
              );
            }
          }

          const speed = calculateSpeed(job.reviews_count, job.scrape_time);
          if (speed === null) return <span className="text-gray-400">-</span>;

          const isGood = speed >= 1;
          const isSlow = speed < 0.5;

          return (
            <span className={`font-medium ${
              isGood ? 'text-green-700' : isSlow ? 'text-orange-600' : 'text-gray-700'
            }`}>
              {speed.toFixed(1)}/s
            </span>
          );
        },
      },
      {
        accessorKey: 'created_at',
        header: ({ column }) => (
          <button
            onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
            className="flex items-center gap-2 hover:text-blue-700 font-semibold"
          >
            Date
            <SortIcon sorted={column.getIsSorted()} />
          </button>
        ),
        cell: ({ row }) => {
          const date = new Date(row.original.created_at);
          const isToday = new Date().toDateString() === date.toDateString();

          return (
            <div>
              <div className="font-medium text-gray-900">
                {isToday ? 'Today' : date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}
              </div>
              <div className="text-xs text-gray-500">
                {date.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' })}
              </div>
            </div>
          );
        },
        sortingFn: (rowA, rowB) => {
          return new Date(rowA.original.created_at).getTime() - new Date(rowB.original.created_at).getTime();
        },
      },
      {
        id: 'actions',
        header: 'Actions',
        cell: ({ row }) => {
          const job = row.original;
          const canView = job.reviews_count && job.reviews_count > 0;
          const isRunning = job.status === 'running';
          const isPartial = job.status === 'partial';
          const previousJob = findPreviousJob(job);

          return (
            <div className="flex items-center gap-2">
              {/* View Reviews - available for any job with reviews */}
              {canView && (
                <button
                  onClick={() => onSelectJob(job, previousJob)}
                  className={`px-2.5 py-1.5 text-xs font-semibold rounded-lg transition-colors flex items-center gap-1.5 ${
                    isRunning
                      ? 'bg-purple-600 text-white hover:bg-purple-700'
                      : isPartial
                      ? 'bg-orange-600 text-white hover:bg-orange-700'
                      : 'bg-blue-600 text-white hover:bg-blue-700'
                  }`}
                  title={isRunning ? 'Preview analytics (job still running)' : isPartial ? 'View partial results' : 'View analytics'}
                >
                  {isLoadingJob === job.job_id ? (
                    <div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" />
                  ) : (
                    <>
                      {isRunning && (
                        <svg className="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
                          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
                        </svg>
                      )}
                      {isRunning ? 'Preview' : isPartial ? 'Partial' : 'View'}
                    </>
                  )}
                </button>
              )}

              {/* Live Monitor - for actively running jobs (not stuck) */}
              {(() => {
                const isStuck = job.status === 'running' &&
                  new Date().getTime() - new Date(job.created_at).getTime() > 10 * 60 * 1000;
                return job.status === 'running' && !isStuck && (
                  <button
                    onClick={() => startMonitoring(job)}
                    className="px-2.5 py-1.5 bg-green-600 text-white text-xs font-semibold rounded-lg hover:bg-green-700 transition-colors flex items-center gap-1.5"
                  >
                    <span className="relative flex h-2 w-2">
                      <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-white opacity-75"></span>
                      <span className="relative inline-flex rounded-full h-2 w-2 bg-white"></span>
                    </span>
                    Live
                  </button>
                );
              })()}

              {/* View DevTools */}
              <Link
                href={`/jobs/${job.job_id}`}
                className="p-1.5 bg-purple-100 text-purple-700 rounded-lg hover:bg-purple-200 transition-colors"
                title="View DevTools"
                onClick={(e) => e.stopPropagation()}
              >
                <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" />
                </svg>
              </Link>

              {/* View Logs */}
              {(() => {
                const isStuck = job.status === 'running' &&
                  new Date().getTime() - new Date(job.created_at).getTime() > 10 * 60 * 1000;
                const isError = job.status === 'failed' || isStuck;
                return (
                  <button
                    onClick={() => fetchJobLogs(job.job_id)}
                    className={`p-1.5 rounded-lg transition-colors ${
                      isError
                        ? 'bg-red-100 text-red-700 hover:bg-red-200'
                        : 'bg-gray-100 text-gray-600 hover:bg-gray-200'
                    }`}
                    title="View logs"
                  >
                    {loadingLogs === job.job_id ? (
                      <div className="w-4 h-4 border-2 border-current border-t-transparent rounded-full animate-spin" />
                    ) : (
                      <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
                      </svg>
                    )}
                  </button>
                );
              })()}

              {/* Expand Error */}
              {job.status === 'failed' && job.error_message && (
                <button
                  onClick={() => {
                    const newExpanded = new Set(expandedErrors);
                    if (newExpanded.has(job.job_id)) {
                      newExpanded.delete(job.job_id);
                    } else {
                      newExpanded.add(job.job_id);
                    }
                    setExpandedErrors(newExpanded);
                  }}
                  className="p-1.5 bg-red-100 text-red-700 rounded-lg hover:bg-red-200 transition-colors"
                  title="Show error"
                >
                  <svg className={`w-4 h-4 transition-transform ${expandedErrors.has(job.job_id) ? 'rotate-180' : ''}`} fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
                  </svg>
                </button>
              )}

              {/* Copy Crash Report - for failed or partial jobs */}
              {(job.status === 'failed' || job.status === 'partial') && (
                <button
                  onClick={() => copyCrashReport(job)}
                  disabled={copyingCrashReport === job.job_id}
                  className={`p-1.5 rounded-lg transition-colors ${
                    copyingCrashReport === job.job_id
                      ? 'bg-green-100 text-green-700'
                      : 'bg-orange-100 text-orange-700 hover:bg-orange-200'
                  }`}
                  title={copyingCrashReport === job.job_id ? 'Copied!' : 'Copy crash report for Claude'}
                >
                  {copyingCrashReport === job.job_id ? (
                    <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>
                  ) : (
                    <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
                    </svg>
                  )}
                </button>
              )}

              {/* Delete Job - allow for non-running or stuck jobs */}
              {(() => {
                const isStuck = job.status === 'running' &&
                  new Date().getTime() - new Date(job.created_at).getTime() > 10 * 60 * 1000;
                const canDelete = job.status !== 'running' || isStuck;

                return canDelete && (
                  <button
                    onClick={() => setDeleteConfirm(job)}
                    className="p-1.5 bg-gray-100 text-gray-500 rounded-lg hover:bg-red-100 hover:text-red-600 transition-colors"
                    title={isStuck ? "Delete stuck job" : "Delete job"}
                  >
                    {isDeleting === job.job_id ? (
                      <div className="w-4 h-4 border-2 border-current border-t-transparent rounded-full animate-spin" />
                    ) : (
                      <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
                      </svg>
                    )}
                  </button>
                );
              })()}
            </div>
          );
        },
      },
    ],
    [isLoadingJob, loadingLogs, expandedErrors, jobsWithUpdates, startMonitoring, isDeleting, copyingCrashReport, copyCrashReport]
  );

  const table = useReactTable({
    data: filteredJobs,
    columns,
    state: {
      sorting,
      globalFilter,
    },
    onSortingChange: setSorting,
    onGlobalFilterChange: setGlobalFilter,
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    globalFilterFn: (row, columnId, filterValue) => {
      const business = extractBusinessName(row.original).toLowerCase();
      const search = filterValue.toLowerCase();
      return business.includes(search);
    },
    initialState: {
      pagination: { pageSize: 20 },
    },
  });

  if (jobs.length === 0) {
    return (
      <div className="flex flex-col items-center justify-center h-full text-gray-500">
        <svg className="w-20 h-20 mb-4 opacity-30" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
        </svg>
        <h3 className="text-xl font-semibold text-gray-700 mb-2">No Jobs Yet</h3>
        <p className="text-sm text-gray-500">Start a new scrape to see your jobs here</p>
      </div>
    );
  }

  return (
    <div className="h-full overflow-y-auto p-6">
      {/* Header */}
      <div className="mb-6">
        <h2 className="text-2xl font-bold text-gray-900">Jobs</h2>
        <p className="text-sm text-gray-600 mt-1">
          Monitor and analyze your scraping jobs
        </p>
      </div>

      {/* Summary Stats */}
      <div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-4 mb-6">
        <StatCard
          label="Total Jobs"
          value={stats.total}
          icon={<ClipboardIcon />}
          color="blue"
        />
        <StatCard
          label="Success Rate"
          value={`${stats.successRate.toFixed(0)}%`}
          icon={<CheckIcon />}
          color={stats.successRate >= 90 ? 'green' : stats.successRate >= 70 ? 'yellow' : 'red'}
        />
        <StatCard
          label="Reviews Scraped"
          value={stats.totalReviews.toLocaleString()}
          icon={<StarIcon />}
          color="purple"
        />
        <StatCard
          label="Avg Duration"
          value={formatDuration(stats.avgTime)}
          icon={<ClockIcon />}
          color="indigo"
        />
        <StatCard
          label="Avg Speed"
          value={`${stats.avgSpeed.toFixed(1)}/s`}
          icon={<SpeedIcon />}
          color={stats.avgSpeed >= 1 ? 'green' : 'orange'}
        />
        <StatCard
          label="Today"
          value={stats.jobsToday}
          icon={<CalendarIcon />}
          color="teal"
        />
      </div>

      {/* Filters */}
      <div className="bg-white border-2 border-gray-200 rounded-xl p-4 mb-6 flex flex-wrap items-center gap-4">
        {/* Search */}
        <div className="relative flex-1 min-w-[200px]">
          <svg className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" 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>
          <input
            type="text"
            placeholder="Search by business name..."
            value={globalFilter}
            onChange={(e) => setGlobalFilter(e.target.value)}
            className="w-full pl-9 pr-4 py-2 border-2 border-gray-200 rounded-lg focus:border-blue-500 focus:outline-none text-sm"
          />
        </div>

        {/* Status Filter */}
        <div className="flex items-center gap-2">
          <span className="text-sm font-medium text-gray-600">Status:</span>
          <div className="flex gap-1">
            {['all', 'completed', 'running', 'failed'].map((status) => (
              <button
                key={status}
                onClick={() => setStatusFilter(status)}
                className={`px-3 py-1.5 text-xs font-semibold rounded-lg transition-colors ${
                  statusFilter === status
                    ? status === 'completed' ? 'bg-green-600 text-white' :
                      status === 'running' ? 'bg-blue-600 text-white' :
                      status === 'failed' ? 'bg-red-600 text-white' :
                      'bg-gray-900 text-white'
                    : 'bg-gray-100 text-gray-600 hover:bg-gray-200'
                }`}
              >
                {status === 'all' ? 'All' : status.charAt(0).toUpperCase() + status.slice(1)}
                {status !== 'all' && (
                  <span className="ml-1 opacity-75">
                    ({status === 'completed' ? stats.completed : status === 'running' ? stats.running : stats.failed})
                  </span>
                )}
              </button>
            ))}
          </div>
        </div>

        {/* Bulk Delete */}
        <div className="flex items-center gap-2 ml-auto">
          <div className="relative group">
            <button
              className="px-3 py-1.5 text-xs font-semibold rounded-lg bg-gray-100 text-gray-600 hover:bg-red-100 hover:text-red-600 transition-colors flex items-center gap-1.5"
            >
              <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
              </svg>
              Bulk Delete
              <svg className="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
              </svg>
            </button>
            <div className="absolute right-0 mt-1 w-48 bg-white border-2 border-gray-200 rounded-lg shadow-lg hidden group-hover:block z-10">
              <button
                onClick={() => setBulkDeleteConfirm('completed')}
                className="w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-100 flex items-center justify-between"
                disabled={stats.completed === 0}
              >
                Delete Completed
                <span className="text-xs text-gray-400">({stats.completed})</span>
              </button>
              <button
                onClick={() => setBulkDeleteConfirm('failed')}
                className="w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-100 flex items-center justify-between"
                disabled={stats.failed === 0}
              >
                Delete Failed
                <span className="text-xs text-gray-400">({stats.failed})</span>
              </button>
              <div className="border-t border-gray-200" />
              <button
                onClick={() => setBulkDeleteConfirm('all')}
                className="w-full px-4 py-2 text-left text-sm text-red-600 hover:bg-red-50 flex items-center justify-between font-semibold"
                disabled={stats.total === 0}
              >
                Delete All Jobs
                <span className="text-xs text-red-400">({stats.total})</span>
              </button>
            </div>
          </div>
        </div>
      </div>

      {/* Table */}
      <div className="bg-white border-2 border-gray-200 rounded-xl overflow-hidden">
        <div className="overflow-x-auto">
          <table className="w-full">
            <thead className="bg-gray-50 border-b-2 border-gray-200">
              {table.getHeaderGroups().map(headerGroup => (
                <tr key={headerGroup.id}>
                  {headerGroup.headers.map(header => (
                    <th key={header.id} className="px-4 py-3 text-left text-sm text-gray-700">
                      {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
                    </th>
                  ))}
                </tr>
              ))}
            </thead>
            <tbody className="divide-y divide-gray-100">
              {table.getRowModel().rows.map(row => (
                <React.Fragment key={row.id}>
                  <tr className="hover:bg-gray-50 transition-colors">
                    {row.getVisibleCells().map(cell => (
                      <td key={cell.id} className="px-4 py-3">
                        {flexRender(cell.column.columnDef.cell, cell.getContext())}
                      </td>
                    ))}
                  </tr>
                  {/* Expanded Error Row */}
                  {expandedErrors.has(row.original.job_id) && row.original.error_message && (
                    <tr className="bg-red-50">
                      <td colSpan={columns.length} className="px-4 py-3">
                        <div className="flex items-start gap-2">
                          <svg className="w-5 h-5 text-red-600 flex-shrink-0 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
                            <path fillRule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clipRule="evenodd" />
                          </svg>
                          <pre className="text-sm text-red-800 font-mono whitespace-pre-wrap break-all">
                            {row.original.error_message}
                          </pre>
                        </div>
                      </td>
                    </tr>
                  )}
                </React.Fragment>
              ))}
            </tbody>
          </table>
        </div>

        {/* Pagination */}
        <div className="px-4 py-3 border-t-2 border-gray-200 flex items-center justify-between bg-gray-50">
          <div className="text-sm text-gray-600">
            Showing {table.getState().pagination.pageIndex * table.getState().pagination.pageSize + 1} to{' '}
            {Math.min((table.getState().pagination.pageIndex + 1) * table.getState().pagination.pageSize, filteredJobs.length)} of{' '}
            {filteredJobs.length} jobs
          </div>
          <div className="flex gap-2">
            <button
              onClick={() => table.previousPage()}
              disabled={!table.getCanPreviousPage()}
              className="px-3 py-1.5 text-sm font-medium border-2 border-gray-200 rounded-lg disabled:opacity-50 disabled:cursor-not-allowed hover:bg-gray-100 transition-colors"
            >
              Previous
            </button>
            <button
              onClick={() => table.nextPage()}
              disabled={!table.getCanNextPage()}
              className="px-3 py-1.5 text-sm font-medium border-2 border-gray-200 rounded-lg disabled:opacity-50 disabled:cursor-not-allowed hover:bg-gray-100 transition-colors"
            >
              Next
            </button>
          </div>
        </div>
      </div>

      {/* Logs Modal */}
      {selectedJobLogs && (
        <div
          className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4"
          onClick={() => setSelectedJobLogs(null)}
        >
          <div
            className="bg-white rounded-2xl shadow-2xl max-w-4xl w-full max-h-[90vh] overflow-hidden flex flex-col"
            onClick={(e) => e.stopPropagation()}
          >
            {/* Modal Header */}
            <div className="bg-gray-100 border-b-2 border-gray-200 px-6 py-4 flex items-center justify-between">
              <div>
                <h3 className="text-xl font-bold text-gray-900">Job Logs</h3>
                <p className="text-sm text-gray-500">
                  {selectedJobLogs.log_count} log entries · Status: {' '}
                  <span className={`font-semibold ${
                    selectedJobLogs.status === 'completed' ? 'text-green-600' :
                    selectedJobLogs.status === 'failed' ? 'text-red-600' :
                    selectedJobLogs.status === 'running' ? 'text-blue-600' :
                    'text-gray-600'
                  }`}>
                    {selectedJobLogs.status}
                  </span>
                </p>
              </div>
              <button
                onClick={() => setSelectedJobLogs(null)}
                className="p-2 hover:bg-gray-200 rounded-full transition-colors"
              >
                <svg className="w-5 h-5 text-gray-600" 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>

            {/* Error Message */}
            {selectedJobLogs.error_message && (
              <div className="bg-red-50 border-b border-red-200 px-6 py-3">
                <div className="flex items-start gap-2">
                  <svg className="w-5 h-5 text-red-600 flex-shrink-0 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
                    <path fillRule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clipRule="evenodd" />
                  </svg>
                  <div>
                    <p className="font-semibold text-red-800">Error</p>
                    <p className="text-sm text-red-700 font-mono whitespace-pre-wrap">{selectedJobLogs.error_message}</p>
                  </div>
                </div>
              </div>
            )}

            {/* Logs List */}
            <div className="flex-1 overflow-y-auto p-4">
              {selectedJobLogs.logs.length === 0 ? (
                <div className="text-center text-gray-500 py-8">
                  <svg className="w-12 h-12 mx-auto mb-3 opacity-30" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
                  </svg>
                  <p className="font-medium">No logs available</p>
                  <p className="text-sm">This job was created before logging was enabled</p>
                </div>
              ) : (
                <div className="space-y-1 font-mono text-sm">
                  {[...selectedJobLogs.logs]
                    .sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime())
                    .map((log, idx) => (
                      <div
                        key={idx}
                        className={`px-3 py-2 rounded-lg ${
                          log.level === 'ERROR' ? 'bg-red-50 border border-red-200' :
                          log.level === 'WARNING' ? 'bg-yellow-50 border border-yellow-200' :
                          log.level === 'INFO' ? 'bg-blue-50 border border-blue-200' :
                          'bg-gray-50 border border-gray-200'
                        }`}
                      >
                        <div className="flex items-start gap-3">
                          <span className="text-gray-400 text-xs whitespace-nowrap">
                            {new Date(log.timestamp).toLocaleTimeString()}
                          </span>
                          <span className={`px-1.5 py-0.5 rounded text-[10px] font-bold ${
                            log.level === 'ERROR' ? 'bg-red-200 text-red-800' :
                            log.level === 'WARNING' ? 'bg-yellow-200 text-yellow-800' :
                            log.level === 'INFO' ? 'bg-blue-200 text-blue-800' :
                            'bg-gray-200 text-gray-700'
                          }`}>
                            {log.level}
                          </span>
                          <span className={`px-1.5 py-0.5 rounded text-[10px] font-semibold ${
                            log.source === 'browser' ? 'bg-purple-100 text-purple-700' : 'bg-green-100 text-green-700'
                          }`}>
                            {log.source}
                          </span>
                          <span className="flex-1 text-gray-800 break-all">
                            {log.message}
                          </span>
                        </div>
                      </div>
                    ))}
                </div>
              )}
            </div>

            {/* Modal Footer */}
            <div className="bg-gray-100 border-t-2 border-gray-200 px-6 py-4">
              <button
                onClick={() => setSelectedJobLogs(null)}
                className="w-full py-2.5 bg-gray-900 text-white rounded-lg font-semibold hover:bg-gray-800 transition-colors"
              >
                Close
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Live Monitor Modal */}
      {monitoredJob && (
        <div
          className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4"
          onClick={() => stopMonitoring()}
        >
          <div
            className="bg-white rounded-2xl shadow-2xl max-w-4xl w-full max-h-[90vh] overflow-hidden flex flex-col"
            onClick={(e) => e.stopPropagation()}
          >
            {/* Modal Header */}
            <div className="bg-gradient-to-r from-green-500 to-emerald-600 px-6 py-4 flex items-center justify-between">
              <div className="flex items-center gap-3">
                <div className="relative">
                  {isMonitoring && (
                    <>
                      <span className="absolute inline-flex h-full w-full rounded-full bg-white opacity-75 animate-ping"></span>
                      <span className="relative inline-flex rounded-full h-3 w-3 bg-white"></span>
                    </>
                  )}
                  {!isMonitoring && (
                    <span className={`inline-flex rounded-full h-3 w-3 ${
                      monitoredJob.status === 'completed' ? 'bg-green-200' :
                      monitoredJob.status === 'failed' ? 'bg-red-300' : 'bg-gray-300'
                    }`}></span>
                  )}
                </div>
                <div>
                  <h3 className="text-xl font-bold text-white">
                    {isMonitoring ? 'Live Monitor' : 'Job Finished'}
                  </h3>
                  <p className="text-sm text-green-100">
                    {extractBusinessName(monitoredJob)}
                  </p>
                </div>
              </div>
              <button
                onClick={() => stopMonitoring()}
                className="p-2 hover:bg-white/20 rounded-full transition-colors"
              >
                <svg className="w-5 h-5 text-white" 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 Section */}
            <div className="px-6 py-4 bg-gray-50 border-b-2 border-gray-200">
              <div className="flex items-center justify-between mb-2">
                <div className="flex items-center gap-3">
                  <span className={`inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-sm font-semibold ${
                    monitoredJob.status === 'completed' ? 'bg-green-100 text-green-800' :
                    monitoredJob.status === 'running' ? 'bg-blue-100 text-blue-800' :
                    monitoredJob.status === 'failed' ? 'bg-red-100 text-red-800' :
                    'bg-gray-100 text-gray-800'
                  }`}>
                    {monitoredJob.status === 'running' && (
                      <div className="w-2.5 h-2.5 border-2 border-current border-t-transparent rounded-full animate-spin" />
                    )}
                    {monitoredJob.status === 'completed' && (
                      <svg className="w-4 h-4" 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>
                    )}
                    {monitoredJob.status === 'failed' && (
                      <svg className="w-4 h-4" 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>
                    )}
                    {monitoredJob.status.charAt(0).toUpperCase() + monitoredJob.status.slice(1)}
                  </span>
                </div>
                <div className="text-right">
                  <div className="text-2xl font-bold text-gray-900">
                    {monitoredJob.reviews_count?.toLocaleString() || 0}
                    {monitoredJob.total_reviews && (
                      <span className="text-gray-400 font-normal text-lg"> / {monitoredJob.total_reviews.toLocaleString()}</span>
                    )}
                  </div>
                  <div className="text-xs text-gray-500">reviews scraped</div>
                </div>
              </div>

              {/* Progress Bar */}
              {monitoredJob.total_reviews && monitoredJob.total_reviews > 0 && (
                <div className="mt-3">
                  <div className="w-full h-3 bg-gray-200 rounded-full overflow-hidden">
                    <div
                      className={`h-full rounded-full transition-all duration-500 ${
                        monitoredJob.status === 'completed' ? 'bg-green-500' :
                        monitoredJob.status === 'failed' ? 'bg-red-500' :
                        'bg-blue-500'
                      }`}
                      style={{ width: `${Math.min(100, ((monitoredJob.reviews_count || 0) / monitoredJob.total_reviews) * 100)}%` }}
                    />
                  </div>
                  <div className="flex justify-between mt-1 text-xs text-gray-500">
                    <span>{Math.round(((monitoredJob.reviews_count || 0) / monitoredJob.total_reviews) * 100)}% complete</span>
                    {monitoredJob.status === 'running' && monitoredJob.reviews_count && monitoredJob.started_at && (
                      <span>
                        {(() => {
                          const endTime = monitoredJob.updated_at ? new Date(monitoredJob.updated_at).getTime() : Date.now();
                          const elapsed = (endTime - new Date(monitoredJob.started_at).getTime()) / 1000;
                          return elapsed > 0 ? (monitoredJob.reviews_count / elapsed).toFixed(1) : '0';
                        })()} reviews/sec
                      </span>
                    )}
                  </div>
                </div>
              )}

              {/* Stats Row */}
              <div className="grid grid-cols-3 gap-4 mt-4">
                <div className="bg-white rounded-lg p-3 border border-gray-200">
                  <div className="text-xs text-gray-500 mb-1">Duration</div>
                  <div className="text-lg font-semibold text-gray-900">
                    {monitoredJob.scrape_time ? formatDuration(monitoredJob.scrape_time) : '-'}
                  </div>
                </div>
                <div className="bg-white rounded-lg p-3 border border-gray-200">
                  <div className="text-xs text-gray-500 mb-1">Speed</div>
                  <div className="text-lg font-semibold text-gray-900">
                    {(() => {
                      if (!monitoredJob.reviews_count || !monitoredJob.started_at) return '-';
                      // For running jobs, use updated_at; for completed, use scrape_time
                      if (monitoredJob.status === 'running') {
                        const endTime = monitoredJob.updated_at ? new Date(monitoredJob.updated_at).getTime() : Date.now();
                        const elapsed = (endTime - new Date(monitoredJob.started_at).getTime()) / 1000;
                        return elapsed > 0 ? `${(monitoredJob.reviews_count / elapsed).toFixed(1)}/s` : '-';
                      }
                      // For completed/partial jobs, use scrape_time if available
                      if (monitoredJob.scrape_time) {
                        return `${(monitoredJob.reviews_count / monitoredJob.scrape_time).toFixed(1)}/s`;
                      }
                      return '-';
                    })()}
                  </div>
                </div>
                <div className="bg-white rounded-lg p-3 border border-gray-200">
                  <div className="text-xs text-gray-500 mb-1">Started</div>
                  <div className="text-lg font-semibold text-gray-900">
                    {monitoredJob.started_at
                      ? new Date(monitoredJob.started_at).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' })
                      : '-'
                    }
                  </div>
                </div>
              </div>
            </div>

            {/* Error Message */}
            {monitoredJob.status === 'failed' && monitoredJob.error_message && (
              <div className="bg-red-50 border-b border-red-200 px-6 py-3">
                <div className="flex items-start gap-2">
                  <svg className="w-5 h-5 text-red-600 flex-shrink-0 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
                    <path fillRule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clipRule="evenodd" />
                  </svg>
                  <div>
                    <p className="font-semibold text-red-800">Error</p>
                    <p className="text-sm text-red-700 font-mono whitespace-pre-wrap">{monitoredJob.error_message}</p>
                  </div>
                </div>
              </div>
            )}

            {/* Live Logs Section */}
            <div className="flex-1 overflow-hidden flex flex-col">
              <div className="px-6 py-2 bg-gray-100 border-b border-gray-200 flex items-center justify-between">
                <div className="flex items-center gap-2">
                  <svg className="w-4 h-4 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
                  </svg>
                  <span className="text-sm font-semibold text-gray-700">Live Logs</span>
                  <span className="text-xs text-gray-500">({monitoredJobLogs.length} entries)</span>
                </div>
                {isMonitoring && (
                  <span className="text-xs text-green-600 flex items-center gap-1">
                    <span className="w-1.5 h-1.5 bg-green-500 rounded-full animate-pulse"></span>
                    Auto-refreshing
                  </span>
                )}
              </div>
              <div className="flex-1 overflow-y-auto p-4 bg-gray-900">
                {monitoredJobLogs.length === 0 ? (
                  <div className="text-center text-gray-500 py-8">
                    <svg className="w-12 h-12 mx-auto mb-3 opacity-30" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
                    </svg>
                    <p className="font-medium text-gray-400">Waiting for logs...</p>
                  </div>
                ) : (
                  <div className="space-y-1 font-mono text-xs">
                    {[...monitoredJobLogs]
                      .sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime())
                      .map((log, idx) => (
                        <div
                          key={idx}
                          className={`px-2 py-1 rounded ${
                            log.level === 'ERROR' ? 'bg-red-900/30 text-red-300' :
                            log.level === 'WARNING' ? 'bg-yellow-900/30 text-yellow-300' :
                            log.level === 'INFO' ? 'text-green-300' :
                            'text-gray-400'
                          }`}
                        >
                          <span className="text-gray-500">
                            {new Date(log.timestamp).toLocaleTimeString()}
                          </span>
                          {' '}
                          <span className={`font-bold ${
                            log.level === 'ERROR' ? 'text-red-400' :
                            log.level === 'WARNING' ? 'text-yellow-400' :
                            log.level === 'INFO' ? 'text-blue-400' :
                            'text-gray-500'
                          }`}>
                            [{log.level}]
                          </span>
                          {' '}
                          <span className={`${
                            log.source === 'browser' ? 'text-purple-400' : 'text-green-400'
                          }`}>
                            [{log.source}]
                          </span>
                          {' '}
                          <span>{log.message}</span>
                        </div>
                      ))}
                  </div>
                )}
              </div>
            </div>

            {/* Modal Footer */}
            <div className="bg-gray-100 border-t-2 border-gray-200 px-6 py-4 flex gap-3">
              {monitoredJob.status === 'completed' && monitoredJob.reviews_count && (
                <button
                  onClick={() => {
                    const previousJob = findPreviousJob(monitoredJob);
                    onSelectJob(monitoredJob, previousJob);
                    stopMonitoring();
                  }}
                  className="flex-1 py-2.5 bg-blue-600 text-white rounded-lg font-semibold hover:bg-blue-700 transition-colors"
                >
                  View Reviews
                </button>
              )}
              <Link
                href={`/jobs/${monitoredJob.job_id}`}
                onClick={() => stopMonitoring()}
                className="py-2.5 px-6 bg-purple-600 text-white rounded-lg font-semibold hover:bg-purple-700 transition-colors flex items-center gap-2"
              >
                <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" />
                </svg>
                DevTools
              </Link>
              <button
                onClick={() => stopMonitoring()}
                className={`${monitoredJob.status === 'completed' && monitoredJob.reviews_count ? '' : 'flex-1'} py-2.5 px-6 bg-gray-900 text-white rounded-lg font-semibold hover:bg-gray-800 transition-colors`}
              >
                Close
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Delete Confirmation Modal */}
      {deleteConfirm && (
        <div
          className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4"
          onClick={() => setDeleteConfirm(null)}
        >
          <div
            className="bg-white rounded-2xl shadow-2xl max-w-md w-full overflow-hidden"
            onClick={(e) => e.stopPropagation()}
          >
            <div className="p-6">
              <div className="flex items-center gap-4 mb-4">
                <div className="w-12 h-12 bg-red-100 rounded-full flex items-center justify-center">
                  <svg className="w-6 h-6 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
                  </svg>
                </div>
                <div>
                  <h3 className="text-lg font-bold text-gray-900">Delete Job</h3>
                  <p className="text-sm text-gray-500">This action cannot be undone</p>
                </div>
              </div>
              <p className="text-gray-700 mb-2">
                Are you sure you want to delete this job?
              </p>
              <div className="bg-gray-100 rounded-lg p-3 mb-4">
                <p className="font-semibold text-gray-900">{extractBusinessName(deleteConfirm)}</p>
                <p className="text-sm text-gray-500">
                  {deleteConfirm.reviews_count ? `${deleteConfirm.reviews_count} reviews` : 'No reviews'} ·{' '}
                  {new Date(deleteConfirm.created_at).toLocaleDateString()}
                </p>
              </div>
            </div>
            <div className="bg-gray-100 px-6 py-4 flex gap-3">
              <button
                onClick={() => setDeleteConfirm(null)}
                className="flex-1 py-2.5 bg-white border-2 border-gray-200 text-gray-700 rounded-lg font-semibold hover:bg-gray-50 transition-colors"
              >
                Cancel
              </button>
              <button
                onClick={() => deleteJob(deleteConfirm.job_id)}
                disabled={isDeleting === deleteConfirm.job_id}
                className="flex-1 py-2.5 bg-red-600 text-white rounded-lg font-semibold hover:bg-red-700 transition-colors disabled:opacity-50 flex items-center justify-center gap-2"
              >
                {isDeleting === deleteConfirm.job_id ? (
                  <>
                    <div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" />
                    Deleting...
                  </>
                ) : (
                  'Delete Job'
                )}
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Bulk Delete Confirmation Modal */}
      {bulkDeleteConfirm && (
        <div
          className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4"
          onClick={() => setBulkDeleteConfirm(null)}
        >
          <div
            className="bg-white rounded-2xl shadow-2xl max-w-md w-full overflow-hidden"
            onClick={(e) => e.stopPropagation()}
          >
            <div className="p-6">
              <div className="flex items-center gap-4 mb-4">
                <div className="w-12 h-12 bg-red-100 rounded-full flex items-center justify-center">
                  <svg className="w-6 h-6 text-red-600" 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>
                  <h3 className="text-lg font-bold text-gray-900">
                    {bulkDeleteConfirm === 'all' ? 'Delete All Jobs' :
                     bulkDeleteConfirm === 'completed' ? 'Delete Completed Jobs' :
                     'Delete Failed Jobs'}
                  </h3>
                  <p className="text-sm text-gray-500">This action cannot be undone</p>
                </div>
              </div>
              <p className="text-gray-700 mb-4">
                {bulkDeleteConfirm === 'all' ? (
                  <>You are about to delete <span className="font-bold text-red-600">{stats.total} jobs</span> and all associated data.</>
                ) : bulkDeleteConfirm === 'completed' ? (
                  <>You are about to delete <span className="font-bold text-red-600">{stats.completed} completed jobs</span> and their reviews data.</>
                ) : (
                  <>You are about to delete <span className="font-bold text-red-600">{stats.failed} failed jobs</span> and their error logs.</>
                )}
              </p>
              <div className="bg-red-50 border border-red-200 rounded-lg p-3">
                <p className="text-sm text-red-800">
                  <strong>Warning:</strong> All reviews data, logs, and job history will be permanently deleted.
                </p>
              </div>
            </div>
            <div className="bg-gray-100 px-6 py-4 flex gap-3">
              <button
                onClick={() => setBulkDeleteConfirm(null)}
                className="flex-1 py-2.5 bg-white border-2 border-gray-200 text-gray-700 rounded-lg font-semibold hover:bg-gray-50 transition-colors"
              >
                Cancel
              </button>
              <button
                onClick={() => bulkDeleteJobs(bulkDeleteConfirm)}
                disabled={isBulkDeleting}
                className="flex-1 py-2.5 bg-red-600 text-white rounded-lg font-semibold hover:bg-red-700 transition-colors disabled:opacity-50 flex items-center justify-center gap-2"
              >
                {isBulkDeleting ? (
                  <>
                    <div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" />
                    Deleting...
                  </>
                ) : (
                  `Delete ${bulkDeleteConfirm === 'all' ? stats.total : bulkDeleteConfirm === 'completed' ? stats.completed : stats.failed} Jobs`
                )}
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

// Helper Components
function SortIcon({ sorted }: { sorted: false | 'asc' | 'desc' }) {
  if (sorted === 'asc') {
    return (
      <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
        <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 15l7-7 7 7" />
      </svg>
    );
  }
  if (sorted === 'desc') {
    return (
      <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
        <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
      </svg>
    );
  }
  return (
    <svg className="w-4 h-4 opacity-30" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4" />
    </svg>
  );
}

function StatCard({ label, value, icon, color }: { label: string; value: string | number; icon: React.ReactNode; color: string }) {
  const colors: Record<string, string> = {
    blue: 'from-blue-100 to-blue-200 border-blue-300 text-blue-900',
    green: 'from-green-100 to-green-200 border-green-300 text-green-900',
    red: 'from-red-100 to-red-200 border-red-300 text-red-900',
    yellow: 'from-yellow-100 to-yellow-200 border-yellow-300 text-yellow-900',
    orange: 'from-orange-100 to-orange-200 border-orange-300 text-orange-900',
    purple: 'from-purple-100 to-purple-200 border-purple-300 text-purple-900',
    indigo: 'from-indigo-100 to-indigo-200 border-indigo-300 text-indigo-900',
    teal: 'from-teal-100 to-teal-200 border-teal-300 text-teal-900',
  };

  return (
    <div className={`bg-gradient-to-br ${colors[color]} border-2 rounded-xl p-4`}>
      <div className="flex items-center gap-2 mb-1">
        <span className="opacity-70">{icon}</span>
        <span className="text-xs font-semibold uppercase tracking-wide opacity-80">{label}</span>
      </div>
      <div className="text-2xl font-bold">{value}</div>
    </div>
  );
}

// Icons
function ClipboardIcon() {
  return (
    <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
    </svg>
  );
}

function CheckIcon() {
  return (
    <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
    </svg>
  );
}

function StarIcon() {
  return (
    <svg className="w-4 h-4" 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>
  );
}

function ClockIcon() {
  return (
    <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
    </svg>
  );
}

function SpeedIcon() {
  return (
    <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
    </svg>
  );
}

function CalendarIcon() {
  return (
    <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
    </svg>
  );
}
