import { useState, useMemo, useEffect } from 'react';
import { Link, useNavigate, useSearchParams } from 'react-router-dom';
import { formatDistanceToNow, subDays, isAfter, isPast, format } from 'date-fns';
import { useAuthStore } from '../../lib/auth';
import { JOB_STATUS_LABELS, getJobStatusLabel } from '../../utils/jobStatusMessages';
import { useJobs, useBulkDeleteJobs, useReprocessJob, useBulkReturnToQC, useCloneJob, useDeleteJob, useUpdateJob } from '../../hooks/useJob';
import { StatusBadge } from '../../components/StatusBadge';
import { useToastContext } from '../../contexts/ToastContext';
import { useGlobalWebSocket } from '../../contexts/GlobalWebSocketContext';
import { apiClient } from '../../lib/api';
import type { Job } from '../../types/api';

// Statuses eligible for bulk download (approved or completed)
const DOWNLOADABLE_STATUSES = ['completed', 'approved_english', 'approved_source'];

// Statuses eligible for "Return to QC" action
const RETURN_TO_QC_ELIGIBLE_STATUSES = [
  'completed', 'pending_final_review', 'rejected', 'qc_feedback',
  'tts_failed', 'render_failed', 'approved_english', 'approved_source',
];

// Status labels imported from shared util (T-1)
const getStatusLabel = getJobStatusLabel;

// Parse date string as UTC (backend returns UTC dates without timezone indicator)
const parseUTCDate = (dateString: string): Date => {
  // If the date string doesn't have timezone info, treat it as UTC
  if (!dateString.endsWith('Z') && !dateString.includes('+') && !dateString.includes('-', 10)) {
    return new Date(dateString + 'Z');
  }
  return new Date(dateString);
};

// Date range filter options
const DATE_RANGE_OPTIONS = [
  { value: '', label: 'All Time' },
  { value: 'last7', label: 'Last 7 Days' },
  { value: 'last30', label: 'Last 30 Days' },
];

// Sortable column header component
interface SortableHeaderProps {
  column: string;
  label: string;
  currentSortColumn: string;
  sortDirection: 'asc' | 'desc';
  onSort: (column: string) => void;
}

function SortableHeader({ column, label, currentSortColumn, sortDirection, onSort }: SortableHeaderProps) {
  const isActive = currentSortColumn === column;

  return (
    <th
      className="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100 select-none"
      onClick={() => onSort(column)}
    >
      <div className="flex items-center space-x-1">
        <span>{label}</span>
        <svg
          className={`w-4 h-4 transition-transform ${isActive ? 'text-gray-700' : 'text-gray-300'} ${isActive && sortDirection === 'asc' ? 'rotate-180' : ''}`}
          fill="currentColor"
          viewBox="0 0 20 20"
        >
          <path fillRule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clipRule="evenodd" />
        </svg>
      </div>
    </th>
  );
}

export function JobsList() {
  const { user } = useAuthStore();
  const toast = useToastContext();
  const navigate = useNavigate();
  const [searchParams] = useSearchParams();

  // Filter state
  const [searchTerm, setSearchTerm] = useState('');
  const [userFilter, setUserFilter] = useState('');
  const [statusFilter, setStatusFilter] = useState('');
  const [dateRangeFilter, setDateRangeFilter] = useState('');
  const [page, setPage] = useState(1);
  const PAGE_SIZE = 50;

  // Sort state
  const [sortColumn, setSortColumn] = useState('created_at');
  const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('desc');

  // Selection and bulk action state
  const [selectedJobs, setSelectedJobs] = useState<Set<string>>(new Set());
  const [bulkAction, setBulkAction] = useState<'delete' | 'reprocess' | 'download' | 'return_to_qc' | ''>('');
  const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
  const [showReprocessConfirm, setShowReprocessConfirm] = useState(false);
  const [showDownloadConfirm, setShowDownloadConfirm] = useState(false);
  const [showReturnToQCConfirm, setShowReturnToQCConfirm] = useState(false);
  const [returnToQCNotes, setReturnToQCNotes] = useState('');
  const [deleteTargetId, setDeleteTargetId] = useState<string | null>(null);
  const [editTarget, setEditTarget] = useState<{ id: string; title: string } | null>(null);
  const [editTitle, setEditTitle] = useState('');
  const [downloadProgress, setDownloadProgress] = useState<{ current: number; total: number } | null>(null);

  // Update filters from URL params (also clears filter when param is absent)
  useEffect(() => {
    const status = searchParams.get('status');
    setStatusFilter(status || '');
    setPage(1);
  }, [searchParams]);

  // Fetch jobs with server-side status filter and pagination
  const { data: jobsData, isLoading, error } = useJobs({
    mine: user?.role === 'client',
    page,
    size: PAGE_SIZE,
    status: statusFilter || undefined,
  });

  const bulkDeleteMutation = useBulkDeleteJobs();
  const deleteJobMutation = useDeleteJob();
  const updateJobMutation = useUpdateJob();
  const reprocessMutation = useReprocessJob();
  const bulkReturnToQCMutation = useBulkReturnToQC();
  const cloneJobMutation = useCloneJob();

  // Get connection status from global WebSocket
  const { connectionStatus } = useGlobalWebSocket();

  // Extract unique users from current jobs for filter dropdown
  const uniqueUsers = useMemo(() => {
    if (!jobsData?.jobs) return [];
    const users = new Map<string, string>();
    jobsData.jobs.forEach((job: Job) => {
      if (job.created_by_name && job.client_id) {
        users.set(job.client_id, job.created_by_name);
      }
    });
    return Array.from(users.entries())
      .map(([id, name]) => ({ value: id, label: name }))
      .sort((a, b) => a.label.localeCompare(b.label));
  }, [jobsData?.jobs]);

  // All possible statuses for the dropdown (static, server-side filtered)
  const uniqueStatuses = Object.keys(JOB_STATUS_LABELS);

  // Handle column sort
  const handleSort = (column: string) => {
    if (sortColumn === column) {
      // Toggle direction if same column
      setSortDirection(sortDirection === 'asc' ? 'desc' : 'asc');
    } else {
      // New column, default to ascending (except created_at which defaults to desc)
      setSortColumn(column);
      setSortDirection(column === 'created_at' ? 'desc' : 'asc');
    }
  };

  // Client-side filtering and sorting
  const filteredAndSortedJobs = useMemo(() => {
    let jobs = jobsData?.jobs || [];

    // Filter by search term (job name, filename, created by user)
    if (searchTerm) {
      const term = searchTerm.toLowerCase();
      jobs = jobs.filter((job: Job) =>
        job.title.toLowerCase().includes(term) ||
        job.source?.original_filename?.toLowerCase().includes(term) ||
        job.created_by_name?.toLowerCase().includes(term)
      );
    }

    // Filter by user
    if (userFilter) {
      jobs = jobs.filter((job: Job) => job.client_id === userFilter);
    }

    // Filter by date range
    if (dateRangeFilter) {
      const now = new Date();
      if (dateRangeFilter === 'last7') {
        const cutoff = subDays(now, 7);
        jobs = jobs.filter((job: Job) => isAfter(parseUTCDate(job.created_at), cutoff));
      } else if (dateRangeFilter === 'last30') {
        const cutoff = subDays(now, 30);
        jobs = jobs.filter((job: Job) => isAfter(parseUTCDate(job.created_at), cutoff));
      }
    }

    // Sort jobs
    jobs = [...jobs].sort((a: Job, b: Job) => {
      let comparison = 0;

      switch (sortColumn) {
        case 'title':
          comparison = a.title.localeCompare(b.title);
          break;
        case 'created_by_name':
          comparison = (a.created_by_name || '').localeCompare(b.created_by_name || '');
          break;
        case 'created_at':
          comparison = parseUTCDate(a.created_at).getTime() - parseUTCDate(b.created_at).getTime();
          break;
        case 'status':
          comparison = a.status.localeCompare(b.status);
          break;
        case 'deadline':
          {
            const da = a.deadline ? parseUTCDate(a.deadline).getTime() : Infinity;
            const db = b.deadline ? parseUTCDate(b.deadline).getTime() : Infinity;
            comparison = da - db;
          }
          break;
        default:
          comparison = 0;
      }

      return sortDirection === 'asc' ? comparison : -comparison;
    });

    return jobs;
  }, [jobsData?.jobs, searchTerm, userFilter, dateRangeFilter, sortColumn, sortDirection]);

  // Clear all filters
  const clearFilters = () => {
    setSearchTerm('');
    setUserFilter('');
    setStatusFilter('');
    setDateRangeFilter('');
    setPage(1);
  };

  // Quick preset filters for PM productivity (PM-9)
  const PM_PRESETS = [
    { label: 'Pending Final Review', status: 'pending_final_review' },
    { label: 'In QC', status: 'pending_qc' },
    { label: 'TTS Failed', status: 'tts_failed' },
    { label: 'Render Failed', status: 'render_failed' },
  ];

  const applyPreset = (status: string) => {
    setStatusFilter(prev => prev === status ? '' : status);
    setPage(1);
  };

  const hasActiveFilters = searchTerm || userFilter || statusFilter || dateRangeFilter;

  // Selection functions
  const toggleJobSelection = (jobId: string) => {
    const newSelected = new Set(selectedJobs);
    if (newSelected.has(jobId)) {
      newSelected.delete(jobId);
    } else {
      newSelected.add(jobId);
    }
    setSelectedJobs(newSelected);
  };

  const selectAll = () => {
    setSelectedJobs(new Set(filteredAndSortedJobs.map(job => job.id)));
  };

  const clearSelection = () => {
    setSelectedJobs(new Set());
    setBulkAction('');
  };

  const handleSingleDelete = async () => {
    if (!deleteTargetId) return;
    try {
      await deleteJobMutation.mutateAsync(deleteTargetId);
      toast.toastOnly.success('Job deleted');
    } catch {
      toast.toastOnly.error('Failed to delete job');
    } finally {
      setDeleteTargetId(null);
    }
  };

  const handleEditSave = async () => {
    if (!editTarget || !editTitle.trim()) return;
    try {
      await updateJobMutation.mutateAsync({ id: editTarget.id, data: { title: editTitle.trim() } as never });
      toast.toastOnly.success('Job renamed');
    } catch {
      toast.toastOnly.error('Failed to rename job');
    } finally {
      setEditTarget(null);
    }
  };

  const handleDeleteConfirm = async () => {
    if (selectedJobs.size === 0) return;

    const jobCount = selectedJobs.size;

    try {
      const result = await bulkDeleteMutation.mutateAsync({
        job_ids: Array.from(selectedJobs)
      });

      if (result.errors.length > 0) {
        toast.toastOnly.warning(`${result.deleted_count}/${jobCount} jobs deleted. Some errors occurred: ${result.errors.join(', ')}`);
      } else {
        toast.toastOnly.success(`${jobCount} job${jobCount > 1 ? 's' : ''} deleted successfully`);
      }

      clearSelection();
      setShowDeleteConfirm(false);
    } catch (error) {
      console.error('Bulk delete failed:', error);
      toast.toastOnly.error('Failed to delete jobs. Please try again.');
    }
  };

  const handleReprocessConfirm = async () => {
    if (selectedJobs.size === 0) return;

    const jobIds = Array.from(selectedJobs);
    let successCount = 0;
    let errorCount = 0;
    const errors: string[] = [];

    try {
      // Process jobs sequentially to avoid overwhelming the system
      for (const jobId of jobIds) {
        try {
          await reprocessMutation.mutateAsync(jobId);
          successCount++;
        } catch (error) {
          errorCount++;
          errors.push(jobId);
          console.error(`Failed to reprocess job ${jobId}:`, error);
        }
      }

      // Show appropriate feedback
      if (successCount === jobIds.length) {
        toast.success(`${successCount} job${successCount > 1 ? 's' : ''} queued for reprocessing`);
      } else if (successCount > 0) {
        toast.warning(`${successCount}/${jobIds.length} jobs queued for reprocessing. ${errorCount} failed.`);
      } else {
        toast.error('Failed to queue jobs for reprocessing. Please try again.');
      }

      clearSelection();
      setShowReprocessConfirm(false);
      setBulkAction('');
    } catch (error) {
      console.error('Bulk reprocess failed:', error);
      toast.error('Failed to reprocess jobs. Please try again.');
    }
  };

  // Check if a job is eligible for bulk download
  const isDownloadableStatus = (status: string) => DOWNLOADABLE_STATUSES.includes(status);

  // Get counts for download confirmation modal
  const getDownloadEligibility = () => {
    const selectedJobsList = filteredAndSortedJobs.filter(job => selectedJobs.has(job.id));
    const eligibleJobs = selectedJobsList.filter(job => isDownloadableStatus(job.status));
    const ineligibleJobs = selectedJobsList.filter(job => !isDownloadableStatus(job.status));
    return { selectedJobsList, eligibleJobs, ineligibleJobs };
  };

  const getReturnToQCEligibility = () => {
    const selectedJobsList = filteredAndSortedJobs.filter(job => selectedJobs.has(job.id));
    const eligibleJobs = selectedJobsList.filter(job => RETURN_TO_QC_ELIGIBLE_STATUSES.includes(job.status));
    const ineligibleJobs = selectedJobsList.filter(job => !RETURN_TO_QC_ELIGIBLE_STATUSES.includes(job.status));
    return { selectedJobsList, eligibleJobs, ineligibleJobs };
  };

  const handleBulkReturnToQC = async () => {
    if (selectedJobs.size === 0 || !returnToQCNotes.trim()) return;

    const eligibleJobIds = filteredAndSortedJobs
      .filter(job => selectedJobs.has(job.id) && RETURN_TO_QC_ELIGIBLE_STATUSES.includes(job.status))
      .map(job => job.id);

    if (eligibleJobIds.length === 0) {
      toast.toastOnly.error('No eligible jobs to return to QC');
      return;
    }

    try {
      const result = await bulkReturnToQCMutation.mutateAsync({
        job_ids: eligibleJobIds,
        notes: returnToQCNotes.trim(),
      });

      if (result.errors.length > 0) {
        toast.toastOnly.warning(
          `${result.returned_count}/${result.total_requested} jobs returned to QC. Some errors occurred.`
        );
      } else {
        toast.toastOnly.success(
          `${result.returned_count} job${result.returned_count !== 1 ? 's' : ''} returned to QC`
        );
      }

      clearSelection();
      setShowReturnToQCConfirm(false);
      setReturnToQCNotes('');
      setBulkAction('');
    } catch (error) {
      console.error('Bulk return to QC failed:', error);
      toast.toastOnly.error('Failed to return jobs to QC. Please try again.');
    }
  };

  const handleBulkDownload = async () => {
    setShowDownloadConfirm(false);

    // Filter to eligible jobs
    const eligibleJobs = filteredAndSortedJobs.filter(
      job => selectedJobs.has(job.id) && isDownloadableStatus(job.status)
    );

    if (eligibleJobs.length === 0) {
      toast.error('No eligible jobs to download');
      return;
    }

    // Show progress indicator
    setDownloadProgress({ current: 0, total: 1 });

    try {
      // Request bulk zip from server
      const blob = await apiClient.bulkDownloadJobs(eligibleJobs.map(j => j.id));

      // Generate filename with timestamp
      const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
      const filename = `accessible_video_${timestamp}.zip`;

      // Trigger browser download
      const blobUrl = URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = blobUrl;
      link.download = filename;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      URL.revokeObjectURL(blobUrl);

      toast.success(`Downloaded ${eligibleJobs.length} job(s) as zip file`);
    } catch (error) {
      console.error('Bulk download failed:', error);
      toast.error('Failed to download files. Please try again.');
    } finally {
      setDownloadProgress(null);
      clearSelection();
    }
  };

  const isAdmin = user?.role === 'admin';
  const isProduction = user?.role === 'production';
  const isPM = user?.role === 'project_manager';
  const canManageJobs = isAdmin || isProduction || isPM;

  const isOverdue = (job: Job) =>
    !!job.deadline &&
    isPast(parseUTCDate(job.deadline)) &&
    !['completed'].includes(job.status);

  const handleCloneJob = async (jobId: string) => {
    try {
      const cloned = await cloneJobMutation.mutateAsync(jobId);
      toast.toastOnly.success('Job cloned successfully');
      navigate(`/jobs/${cloned.id}`);
    } catch {
      toast.toastOnly.error('Failed to clone job');
    }
  };
  const canBulkDelete = canManageJobs && selectedJobs.size > 0;
  const canBulkReprocess = canManageJobs && selectedJobs.size > 0;

  const getActionButton = (job: Job) => {
    const isReviewer = ['reviewer', 'production', 'admin', 'project_manager'].includes(user?.role || '');

    switch (job.status) {
      case 'pending_qc':
        return isReviewer ? (
          <Link
            to={`/admin/qc/${job.id}`}
            className="inline-flex items-center px-3 py-1 border border-transparent text-sm font-medium rounded-md text-yellow-700 bg-yellow-100 hover:bg-yellow-200"
          >
            Review
          </Link>
        ) : null;
      case 'pending_final_review':
        return isReviewer ? (
          <Link
            to={`/admin/final/${job.id}`}
            className="inline-flex items-center px-3 py-1 border border-transparent text-sm font-medium rounded-md text-green-700 bg-green-100 hover:bg-green-200"
          >
            Final Review
          </Link>
        ) : null;
      case 'completed':
        return (
          <Link
            to={`/downloads/${job.id}`}
            className="inline-flex items-center px-3 py-1 border border-transparent text-sm font-medium rounded-md text-indigo-700 bg-indigo-100 hover:bg-indigo-200"
          >
            <svg className="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 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>
            Download
          </Link>
        );
      default:
        return null;
    }
  };

  const getConnectionStatusIcon = () => {
    switch (connectionStatus) {
      case 'connected':
        return <span className="inline-block w-2 h-2 bg-green-400 rounded-full" title="Connected - real-time updates enabled" />;
      case 'connecting':
        return <span className="inline-block w-2 h-2 bg-yellow-400 rounded-full animate-pulse" title="Connecting..." />;
      case 'disconnected':
        return <span className="inline-block w-2 h-2 bg-gray-400 rounded-full" title="Disconnected - using cached data" />;
      case 'error':
        return <span className="inline-block w-2 h-2 bg-red-400 rounded-full" title="Connection error" />;
      default:
        return null;
    }
  };

  const sortProps = {
    currentSortColumn: sortColumn,
    sortDirection,
    onSort: handleSort,
  };

  return (
    <div className="container mx-auto px-4 py-8">
      {/* Header */}
      <div className="flex justify-between items-center mb-8">
        <div>
          <div className="flex items-center gap-3">
            <h1 className="text-3xl font-bold text-gray-900">All Jobs</h1>
            {getConnectionStatusIcon()}
          </div>
          <p className="text-gray-600 mt-1">
            {user?.role === 'client' ? 'Your video processing jobs' : 'System-wide job management'}
          </p>
        </div>

        {['client', 'production', 'admin', 'project_manager'].includes(user?.role || '') && (
          <Link
            to="/jobs/new"
            className="bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors inline-flex items-center"
          >
            <svg className="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
            </svg>
            New Job
          </Link>
        )}
      </div>

      {/* Quick filter presets — shown for PM and admin */}
      {(isPM || isAdmin) && (
        <div className="flex flex-wrap gap-2 mb-4">
          {PM_PRESETS.map(preset => (
            <button
              key={preset.status}
              onClick={() => applyPreset(preset.status)}
              className={`px-3 py-1.5 text-sm rounded-full border transition-colors ${
                statusFilter === preset.status
                  ? 'bg-blue-600 border-blue-600 text-white'
                  : 'bg-white border-gray-300 text-gray-700 hover:border-blue-400 hover:text-blue-600'
              }`}
            >
              {preset.label}
            </button>
          ))}
        </div>
      )}

      {/* Filters and Search */}
      <div className="bg-white rounded-lg border border-gray-200 p-6 mb-6">
        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-6 gap-4">
          {/* Search - spans 2 columns */}
          <div className="lg:col-span-2">
            <label htmlFor="search" className="block text-sm font-medium text-gray-700 mb-2">
              Search
            </label>
            <input
              type="text"
              id="search"
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
              placeholder="Search by job name, user, or filename..."
              className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
            />
          </div>

          {/* User Filter */}
          <div>
            <label htmlFor="userFilter" className="block text-sm font-medium text-gray-700 mb-2">
              Created By
            </label>
            <select
              id="userFilter"
              value={userFilter}
              onChange={(e) => setUserFilter(e.target.value)}
              className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
            >
              <option value="">All Users</option>
              {uniqueUsers.map((user) => (
                <option key={user.value} value={user.value}>
                  {user.label}
                </option>
              ))}
            </select>
          </div>

          {/* Status Filter */}
          <div>
            <label htmlFor="statusFilter" className="block text-sm font-medium text-gray-700 mb-2">
              Status
            </label>
            <select
              id="statusFilter"
              value={statusFilter}
              onChange={(e) => setStatusFilter(e.target.value)}
              className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
            >
              <option value="">All Statuses</option>
              {uniqueStatuses.map((status) => (
                <option key={status} value={status}>
                  {getStatusLabel(status)}
                </option>
              ))}
            </select>
          </div>

          {/* Date Range Filter */}
          <div>
            <label htmlFor="dateRangeFilter" className="block text-sm font-medium text-gray-700 mb-2">
              Date Created
            </label>
            <select
              id="dateRangeFilter"
              value={dateRangeFilter}
              onChange={(e) => setDateRangeFilter(e.target.value)}
              className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
            >
              {DATE_RANGE_OPTIONS.map((option) => (
                <option key={option.value} value={option.value}>
                  {option.label}
                </option>
              ))}
            </select>
          </div>

          {/* Clear Filters Button */}
          <div className="flex items-end">
            <button
              onClick={clearFilters}
              disabled={!hasActiveFilters}
              className="w-full px-3 py-2 text-sm text-gray-600 border border-gray-300 rounded-md hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed"
            >
              Clear Filters
            </button>
          </div>
        </div>
      </div>

      {/* Bulk Actions - Only show for production/admin users */}
      {canManageJobs && filteredAndSortedJobs.length > 0 && (
        <div className="bg-white border border-gray-200 rounded-lg p-4 mb-4">
          <div className="flex flex-wrap items-center gap-4">
            <div className="flex items-center space-x-2">
              <input
                type="checkbox"
                checked={selectedJobs.size === filteredAndSortedJobs.length && filteredAndSortedJobs.length > 0}
                onChange={() => selectedJobs.size === filteredAndSortedJobs.length ? clearSelection() : selectAll()}
                className="rounded border-gray-300"
              />
              <span className="text-sm text-gray-700">
                {selectedJobs.size > 0 ? `${selectedJobs.size} selected` : 'Select all'}
              </span>
            </div>

            {(canBulkDelete || canBulkReprocess) && (
              <>
                <select
                  value={bulkAction}
                  onChange={(e) => setBulkAction(e.target.value as 'delete' | 'reprocess' | 'download' | 'return_to_qc' | '')}
                  disabled={bulkDeleteMutation.isPending || reprocessMutation.isPending || bulkReturnToQCMutation.isPending}
                  className="text-sm border border-gray-300 rounded px-2 py-1 disabled:opacity-50 disabled:cursor-not-allowed"
                >
                  <option value="">Choose action...</option>
                  <option value="delete">Delete Selected</option>
                  <option value="reprocess">Reprocess Selected</option>
                  <option value="download">Download All Files</option>
                  <option value="return_to_qc">Return to QC</option>
                </select>

                {bulkAction === 'delete' && (
                  <button
                    onClick={() => setShowDeleteConfirm(true)}
                    disabled={bulkDeleteMutation.isPending}
                    className="px-3 py-1 text-sm bg-red-600 text-white rounded hover:bg-red-700 disabled:opacity-50 disabled:cursor-not-allowed"
                  >
                    {bulkDeleteMutation.isPending ? 'Deleting...' : 'Delete'}
                  </button>
                )}

                {bulkAction === 'reprocess' && (
                  <button
                    onClick={() => setShowReprocessConfirm(true)}
                    disabled={reprocessMutation.isPending}
                    className="px-3 py-1 text-sm bg-orange-600 text-white rounded hover:bg-orange-700 disabled:opacity-50 disabled:cursor-not-allowed"
                  >
                    {reprocessMutation.isPending ? 'Reprocessing...' : 'Reprocess'}
                  </button>
                )}

                {bulkAction === 'download' && (
                  <button
                    onClick={() => setShowDownloadConfirm(true)}
                    disabled={downloadProgress !== null}
                    className="px-3 py-1 text-sm bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed"
                  >
                    Download Files
                  </button>
                )}

                {bulkAction === 'return_to_qc' && (
                  <button
                    onClick={() => setShowReturnToQCConfirm(true)}
                    disabled={bulkReturnToQCMutation.isPending}
                    className="px-3 py-1 text-sm bg-amber-600 text-white rounded hover:bg-amber-700 disabled:opacity-50 disabled:cursor-not-allowed"
                  >
                    {bulkReturnToQCMutation.isPending ? 'Returning...' : 'Return to QC'}
                  </button>
                )}

                <button
                  onClick={clearSelection}
                  className="px-3 py-1 text-sm text-gray-600 hover:text-gray-800"
                >
                  Clear
                </button>
              </>
            )}
          </div>
        </div>
      )}

      {/* Results Summary */}
      <div className="flex justify-between items-center mb-4">
        <p className="text-sm text-gray-600">
          {jobsData?.total
            ? `Showing ${(page - 1) * PAGE_SIZE + 1}–${Math.min(page * PAGE_SIZE, jobsData.total)} of ${jobsData.total} jobs`
            : 'No jobs found'}
        </p>
        {hasActiveFilters && (
          <button
            onClick={clearFilters}
            className="text-sm text-blue-600 hover:text-blue-700"
          >
            Clear all filters
          </button>
        )}
      </div>

      {/* Jobs Table */}
      <div className="bg-white rounded-lg border border-gray-200 overflow-hidden">
        {isLoading ? (
          <div className="p-6">
            <div className="animate-pulse space-y-4">
              {[...Array(5)].map((_, i) => (
                <div key={i} className="h-12 bg-gray-200 rounded"></div>
              ))}
            </div>
          </div>
        ) : error ? (
          <div className="p-6 text-center text-red-600">
            Error loading jobs. Please try again.
          </div>
        ) : filteredAndSortedJobs.length === 0 ? (
          <div className="p-8 text-center text-gray-500">
            {hasActiveFilters ? (
              <>
                <p>No jobs found matching your filters</p>
                <button
                  onClick={clearFilters}
                  className="mt-2 text-blue-600 hover:text-blue-700"
                >
                  Clear filters to see all jobs
                </button>
              </>
            ) : (
              <p>
                No jobs found.{' '}
                {['client', 'production', 'admin', 'project_manager'].includes(user?.role || '') && (
                  <Link to="/jobs/new" className="text-blue-600 hover:text-blue-700">
                    Upload your first video to get started!
                  </Link>
                )}
              </p>
            )}
          </div>
        ) : (
          <div className="overflow-x-auto">
            <table className="min-w-full divide-y divide-gray-200">
              <thead className="bg-gray-50">
                <tr>
                  {/* Checkbox column */}
                  {canManageJobs && (
                    <th className="px-4 py-3 w-10">
                      <input
                        type="checkbox"
                        checked={selectedJobs.size === filteredAndSortedJobs.length && filteredAndSortedJobs.length > 0}
                        onChange={() => selectedJobs.size === filteredAndSortedJobs.length ? clearSelection() : selectAll()}
                        className="rounded border-gray-300"
                      />
                    </th>
                  )}
                  <SortableHeader column="title" label="Job Name" {...sortProps} />
                  <SortableHeader column="created_by_name" label="Created By" {...sortProps} />
                  <SortableHeader column="created_at" label="Date Created" {...sortProps} />
                  <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                    Languages
                  </th>
                  <SortableHeader column="status" label="Status" {...sortProps} />
                  <SortableHeader column="deadline" label="Deadline" {...sortProps} />
                  <th className="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">
                    Actions
                  </th>
                </tr>
              </thead>
              <tbody className="bg-white divide-y divide-gray-200">
                {filteredAndSortedJobs.map((job: Job) => (
                  <tr key={job.id} className="hover:bg-gray-50">
                    {/* Checkbox */}
                    {canManageJobs && (
                      <td className="px-4 py-4 whitespace-nowrap">
                        <input
                          type="checkbox"
                          checked={selectedJobs.has(job.id)}
                          onChange={() => toggleJobSelection(job.id)}
                          className="rounded border-gray-300"
                          onClick={(e) => e.stopPropagation()}
                        />
                      </td>
                    )}
                    {/* Job Name */}
                    <td className="px-4 py-4 whitespace-nowrap">
                      <div className="flex items-center gap-2">
                        <Link
                          to={`/jobs/${job.id}`}
                          className="text-sm font-medium text-gray-900 hover:text-blue-600"
                        >
                          {job.title}
                        </Link>
                        {/* TTS Rewrite Caution Indicator */}
                        {job.tts_rewrites && job.tts_rewrites.length > 0 && (
                          <span
                            title={`${job.tts_rewrites.length} cue${job.tts_rewrites.length > 1 ? 's were' : ' was'} auto-rewritten for TTS`}
                            className="inline-flex items-center"
                          >
                            <svg className="w-4 h-4 text-amber-500" 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>
                        )}
                      </div>
                    </td>
                    {/* Created By */}
                    <td className="px-4 py-4 whitespace-nowrap text-sm text-gray-500">
                      {job.created_by_name || 'Unknown'}
                    </td>
                    {/* Date Created */}
                    <td className="px-4 py-4 whitespace-nowrap text-sm text-gray-500">
                      {formatDistanceToNow(parseUTCDate(job.created_at))} ago
                    </td>
                    {/* Languages Count (includes source language) */}
                    <td className="px-4 py-4 whitespace-nowrap text-sm text-gray-500">
                      {(job.requested_outputs?.languages?.length || 0) + 1}
                    </td>
                    {/* Status Badge */}
                    <td className="px-4 py-4 whitespace-nowrap">
                      <StatusBadge status={job.status} />
                    </td>
                    {/* Deadline */}
                    <td className="px-4 py-4 whitespace-nowrap text-sm">
                      {job.deadline ? (
                        <span className={isOverdue(job) ? 'text-red-600 font-medium' : 'text-gray-500'}>
                          {isOverdue(job) && (
                            <span className="mr-1" title="Overdue">⚠</span>
                          )}
                          {format(parseUTCDate(job.deadline), 'dd MMM yyyy')}
                        </span>
                      ) : (
                        <span className="text-gray-300">—</span>
                      )}
                    </td>
                    {/* Actions */}
                    <td className="px-4 py-4 whitespace-nowrap text-right text-sm font-medium">
                      <div className="flex items-center justify-end gap-2">
                        {getActionButton(job)}
                        {canManageJobs && (
                          <>
                            <button
                              onClick={() => { setEditTarget({ id: job.id, title: job.title }); setEditTitle(job.title); }}
                              title="Rename job"
                              className="inline-flex items-center px-2 py-1 text-xs border border-gray-300 rounded text-gray-600 hover:bg-gray-50"
                            >
                              Edit
                            </button>
                            <button
                              onClick={() => handleCloneJob(job.id)}
                              disabled={cloneJobMutation.isPending}
                              title="Clone job"
                              className="inline-flex items-center px-2 py-1 text-xs border border-gray-300 rounded text-gray-600 hover:bg-gray-50 disabled:opacity-50"
                            >
                              Clone
                            </button>
                            <button
                              onClick={() => setDeleteTargetId(job.id)}
                              title="Delete job"
                              className="inline-flex items-center px-2 py-1 text-xs border border-red-200 rounded text-red-600 hover:bg-red-50"
                            >
                              Delete
                            </button>
                          </>
                        )}
                      </div>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>

      {/* Pagination */}
      {jobsData && jobsData.total > PAGE_SIZE && (
        <div className="flex justify-center items-center gap-2 mt-6">
          <button
            onClick={() => setPage(p => Math.max(1, p - 1))}
            disabled={page === 1}
            className="px-3 py-2 text-sm border border-gray-300 rounded-md hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed"
          >
            Previous
          </button>
          {Array.from({ length: Math.ceil(jobsData.total / PAGE_SIZE) }, (_, i) => i + 1)
            .filter(p => p === 1 || p === Math.ceil(jobsData.total / PAGE_SIZE) || Math.abs(p - page) <= 2)
            .reduce<(number | 'ellipsis')[]>((acc, p, idx, arr) => {
              if (idx > 0 && (arr[idx - 1] as number) + 1 < p) acc.push('ellipsis');
              acc.push(p);
              return acc;
            }, [])
            .map((item, idx) =>
              item === 'ellipsis' ? (
                <span key={`e-${idx}`} className="px-2 text-gray-400">…</span>
              ) : (
                <button
                  key={item}
                  onClick={() => setPage(item as number)}
                  className={`px-3 py-2 text-sm border rounded-md ${
                    page === item
                      ? 'bg-blue-600 border-blue-600 text-white'
                      : 'border-gray-300 hover:bg-gray-50'
                  }`}
                >
                  {item}
                </button>
              )
            )}
          <button
            onClick={() => setPage(p => Math.min(Math.ceil(jobsData.total / PAGE_SIZE), p + 1))}
            disabled={page >= Math.ceil(jobsData.total / PAGE_SIZE)}
            className="px-3 py-2 text-sm border border-gray-300 rounded-md hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed"
          >
            Next
          </button>
        </div>
      )}

      {/* Delete Confirmation Modal */}
      {showDeleteConfirm && (
        <div className="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full z-50">
          <div className="relative top-20 mx-auto p-5 border w-96 shadow-lg rounded-md bg-white">
            <div className="mt-3 text-center">
              <div className="mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-red-100">
                <svg
                  className="h-6 w-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-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z"
                  />
                </svg>
              </div>
              <h3 className="text-lg font-medium text-gray-900 mt-4">
                Delete {selectedJobs.size} Job{selectedJobs.size !== 1 ? 's' : ''}?
              </h3>
              <div className="mt-2 px-7 py-3">
                <p className="text-sm text-gray-500">
                  Are you sure you want to delete the selected job{selectedJobs.size !== 1 ? 's' : ''}?
                  This will permanently remove:
                </p>
                <ul className="mt-2 text-sm text-gray-500 text-left">
                  <li>- All video files and assets</li>
                  <li>- Generated captions and audio descriptions</li>
                  <li>- Translation files</li>
                  <li>- Processing history</li>
                </ul>
                <p className="mt-2 text-sm text-red-600 font-medium">
                  This action cannot be undone.
                </p>
              </div>
              {bulkDeleteMutation.isPending ? (
                <div className="px-4 py-3 flex flex-col items-center space-y-2">
                  <div className="flex items-center gap-3">
                    <div className="animate-spin h-5 w-5 border-2 border-red-600 border-t-transparent rounded-full" />
                    <span className="text-sm text-gray-700">
                      Deleting {selectedJobs.size} job{selectedJobs.size !== 1 ? 's' : ''}...
                    </span>
                  </div>
                  <p className="text-xs text-gray-500">Please wait, this may take a moment.</p>
                </div>
              ) : (
                <div className="items-center px-4 py-3 flex flex-col space-y-2 sm:flex-row sm:space-y-0 sm:space-x-3">
                  <button
                    onClick={() => setShowDeleteConfirm(false)}
                    className="px-4 py-2 bg-gray-500 text-white text-base font-medium rounded-md w-full shadow-sm hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-gray-300 sm:w-auto"
                  >
                    Cancel
                  </button>
                  <button
                    onClick={handleDeleteConfirm}
                    className="px-4 py-2 bg-red-600 text-white text-base font-medium rounded-md w-full shadow-sm hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-300 sm:w-auto"
                  >
                    Delete
                  </button>
                </div>
              )}
            </div>
          </div>
        </div>
      )}

      {/* Reprocess Confirmation Modal */}
      {showReprocessConfirm && (
        <div className="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full z-50">
          <div className="relative top-20 mx-auto p-5 border w-96 shadow-lg rounded-md bg-white">
            <div className="mt-3 text-center">
              <div className="mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-orange-100">
                <svg
                  className="h-6 w-6 text-orange-600"
                  fill="none"
                  stroke="currentColor"
                  viewBox="0 0 24 24"
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    strokeWidth="2"
                    d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
                  />
                </svg>
              </div>
              <h3 className="text-lg font-medium text-gray-900 mt-4">
                Reprocess {selectedJobs.size} Job{selectedJobs.size !== 1 ? 's' : ''}?
              </h3>
              <div className="mt-2 px-7 py-3">
                <p className="text-sm text-gray-500">
                  This will reset the selected job{selectedJobs.size !== 1 ? 's' : ''} and restart processing from the beginning.
                </p>
                <div className="mt-3 p-3 bg-yellow-50 rounded-md">
                  <div className="text-sm text-yellow-800">
                    <strong>Warning:</strong> This will:
                  </div>
                  <ul className="mt-2 text-sm text-yellow-700 text-left">
                    <li>- Reset job status to "created"</li>
                    <li>- Restart AI processing from scratch</li>
                    <li>- Overwrite existing results</li>
                    <li>- Require re-review and re-approval</li>
                  </ul>
                </div>
                <p className="mt-2 text-sm text-orange-600 font-medium">
                  Use this only for stuck or failed jobs.
                </p>
              </div>
              <div className="items-center px-4 py-3 flex flex-col space-y-2 sm:flex-row sm:space-y-0 sm:space-x-3">
                <button
                  onClick={() => setShowReprocessConfirm(false)}
                  className="px-4 py-2 bg-gray-500 text-white text-base font-medium rounded-md w-full shadow-sm hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-gray-300 sm:w-auto"
                >
                  Cancel
                </button>
                <button
                  onClick={handleReprocessConfirm}
                  disabled={reprocessMutation.isPending}
                  className="px-4 py-2 bg-orange-600 text-white text-base font-medium rounded-md w-full shadow-sm hover:bg-orange-700 focus:outline-none focus:ring-2 focus:ring-orange-300 disabled:opacity-50 sm:w-auto"
                >
                  {reprocessMutation.isPending ? 'Reprocessing...' : 'Reprocess'}
                </button>
              </div>
            </div>
          </div>
        </div>
      )}

      {/* Download Confirmation Modal */}
      {showDownloadConfirm && (() => {
        const { eligibleJobs, ineligibleJobs } = getDownloadEligibility();
        return (
          <div className="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full z-50">
            <div className="relative top-20 mx-auto p-5 border w-96 shadow-lg rounded-md bg-white">
              <div className="mt-3 text-center">
                <div className="mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-blue-100">
                  <svg
                    className="h-6 w-6 text-blue-600"
                    fill="none"
                    stroke="currentColor"
                    viewBox="0 0 24 24"
                  >
                    <path
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      strokeWidth="2"
                      d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 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>
                </div>
                <h3 className="text-lg font-medium text-gray-900 mt-4">
                  Download All Files
                </h3>
                <div className="mt-2 px-4 py-3">
                  <p className="text-sm text-gray-700">
                    You have selected <span className="font-semibold">{selectedJobs.size}</span> job{selectedJobs.size !== 1 ? 's' : ''}.{' '}
                    <span className="font-semibold text-blue-600">{eligibleJobs.length}</span>{' '}
                    {eligibleJobs.length === 1 ? 'is' : 'are'} eligible for download.
                  </p>

                  {ineligibleJobs.length > 0 && (
                    <div className="mt-3 p-3 bg-yellow-50 rounded-md">
                      <p className="text-sm text-yellow-800">
                        <strong>{ineligibleJobs.length}</strong> job{ineligibleJobs.length !== 1 ? 's are' : ' is'} not in approved/completed status and will be skipped.
                      </p>
                    </div>
                  )}

                  {eligibleJobs.length > 0 && (
                    <div className="mt-3 text-left">
                      <p className="text-sm text-gray-600 mb-2">Files to be downloaded per eligible job:</p>
                      <ul className="text-sm text-gray-500 space-y-1">
                        <li>- Source video (MP4)</li>
                        <li>- Captions (VTT) for all languages</li>
                        <li>- Audio descriptions (VTT + MP3) for all languages</li>
                        <li>- Accessible videos (MP4 with AD pauses)</li>
                        <li>- Re-timed captions (VTT synced to accessible video)</li>
                      </ul>
                    </div>
                  )}
                </div>
                <div className="items-center px-4 py-3 flex flex-col space-y-2 sm:flex-row sm:space-y-0 sm:space-x-3">
                  <button
                    onClick={() => setShowDownloadConfirm(false)}
                    className="px-4 py-2 bg-gray-500 text-white text-base font-medium rounded-md w-full shadow-sm hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-gray-300 sm:w-auto"
                  >
                    Cancel
                  </button>
                  <button
                    onClick={handleBulkDownload}
                    disabled={eligibleJobs.length === 0}
                    className="px-4 py-2 bg-blue-600 text-white text-base font-medium rounded-md w-full shadow-sm hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-300 disabled:opacity-50 disabled:cursor-not-allowed sm:w-auto"
                  >
                    Download
                  </button>
                </div>
              </div>
            </div>
          </div>
        );
      })()}

      {/* Return to QC Confirmation Modal */}
      {showReturnToQCConfirm && (() => {
        const { eligibleJobs, ineligibleJobs } = getReturnToQCEligibility();
        return (
          <div className="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full z-50">
            <div className="relative top-20 mx-auto p-5 border w-96 shadow-lg rounded-md bg-white">
              <div className="mt-3 text-center">
                <div className="mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-amber-100">
                  <svg
                    className="h-6 w-6 text-amber-600"
                    fill="none"
                    stroke="currentColor"
                    viewBox="0 0 24 24"
                  >
                    <path
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      strokeWidth="2"
                      d="M3 10h10a8 8 0 018 8v2M3 10l6 6m-6-6l6-6"
                    />
                  </svg>
                </div>
                <h3 className="text-lg font-medium text-gray-900 mt-4">
                  Return {selectedJobs.size} Job{selectedJobs.size !== 1 ? 's' : ''} to QC?
                </h3>
                <div className="mt-2 px-4 py-3">
                  <p className="text-sm text-gray-700">
                    <span className="font-semibold text-amber-600">{eligibleJobs.length}</span>{' '}
                    of {selectedJobs.size} selected job{selectedJobs.size !== 1 ? 's are' : ' is'} eligible to return to QC.
                  </p>

                  {ineligibleJobs.length > 0 && (
                    <div className="mt-3 p-3 bg-yellow-50 rounded-md">
                      <p className="text-sm text-yellow-800">
                        <strong>{ineligibleJobs.length}</strong> job{ineligibleJobs.length !== 1 ? 's are' : ' is'} not in an eligible status and will be skipped.
                      </p>
                    </div>
                  )}

                  <div className="mt-3 p-3 bg-amber-50 rounded-md text-left">
                    <div className="text-sm text-amber-800">
                      <strong>This will:</strong>
                    </div>
                    <ul className="mt-1 text-sm text-amber-700">
                      <li>- Move jobs back to QC review status</li>
                      <li>- Allow re-editing of captions and audio descriptions</li>
                      <li>- Require re-approval before final review</li>
                    </ul>
                  </div>

                  <div className="mt-3 text-left">
                    <label className="block text-sm font-medium text-gray-700 mb-1">
                      Reason for returning to QC <span className="text-red-500">*</span>
                    </label>
                    <textarea
                      value={returnToQCNotes}
                      onChange={(e) => setReturnToQCNotes(e.target.value)}
                      placeholder="Describe why these jobs need to be returned to QC..."
                      rows={3}
                      className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-amber-500 text-sm"
                    />
                  </div>
                </div>
                <div className="items-center px-4 py-3 flex flex-col space-y-2 sm:flex-row sm:space-y-0 sm:space-x-3">
                  <button
                    onClick={() => { setShowReturnToQCConfirm(false); setReturnToQCNotes(''); }}
                    className="px-4 py-2 bg-gray-500 text-white text-base font-medium rounded-md w-full shadow-sm hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-gray-300 sm:w-auto"
                  >
                    Cancel
                  </button>
                  <button
                    onClick={handleBulkReturnToQC}
                    disabled={eligibleJobs.length === 0 || !returnToQCNotes.trim() || bulkReturnToQCMutation.isPending}
                    className="px-4 py-2 bg-amber-600 text-white text-base font-medium rounded-md w-full shadow-sm hover:bg-amber-700 focus:outline-none focus:ring-2 focus:ring-amber-300 disabled:opacity-50 disabled:cursor-not-allowed sm:w-auto"
                  >
                    {bulkReturnToQCMutation.isPending ? 'Returning...' : 'Return to QC'}
                  </button>
                </div>
              </div>
            </div>
          </div>
        );
      })()}

      {/* Single-job delete confirmation */}
      {deleteTargetId && (
        <div className="fixed inset-0 bg-black/40 flex items-center justify-center z-50">
          <div className="bg-white rounded-lg shadow-xl p-6 max-w-sm w-full mx-4 space-y-4">
            <h3 className="text-base font-semibold text-gray-900">Delete job?</h3>
            <p className="text-sm text-gray-600">
              This will permanently delete the job, all generated files, and source video from storage. This cannot be undone.
            </p>
            <div className="flex gap-3 justify-end pt-1">
              <button
                onClick={() => setDeleteTargetId(null)}
                className="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50"
              >
                Cancel
              </button>
              <button
                onClick={handleSingleDelete}
                disabled={deleteJobMutation.isPending}
                className="px-4 py-2 text-sm font-medium text-white bg-red-600 rounded-md hover:bg-red-700 disabled:opacity-50"
              >
                {deleteJobMutation.isPending ? 'Deleting…' : 'Delete'}
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Rename job modal */}
      {editTarget && (
        <div className="fixed inset-0 bg-black/40 flex items-center justify-center z-50">
          <div className="bg-white rounded-lg shadow-xl p-6 max-w-sm w-full mx-4 space-y-4">
            <h3 className="text-base font-semibold text-gray-900">Rename job</h3>
            <input
              type="text"
              value={editTitle}
              onChange={e => setEditTitle(e.target.value)}
              onKeyDown={e => { if (e.key === 'Enter') handleEditSave(); if (e.key === 'Escape') setEditTarget(null); }}
              className="w-full border border-gray-300 rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500"
              autoFocus
            />
            <div className="flex gap-3 justify-end pt-1">
              <button
                onClick={() => setEditTarget(null)}
                className="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50"
              >
                Cancel
              </button>
              <button
                onClick={handleEditSave}
                disabled={updateJobMutation.isPending || !editTitle.trim()}
                className="px-4 py-2 text-sm font-medium text-white bg-indigo-600 rounded-md hover:bg-indigo-700 disabled:opacity-50"
              >
                {updateJobMutation.isPending ? 'Saving…' : 'Save'}
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Download Progress Indicator */}
      {downloadProgress && (
        <div className="fixed bottom-4 right-4 bg-white rounded-lg shadow-lg p-4 z-50 border border-gray-200">
          <div className="flex items-center gap-3">
            <div className="animate-spin h-5 w-5 border-2 border-blue-600 border-t-transparent rounded-full" />
            <span className="text-sm text-gray-700">
              Preparing zip file...
            </span>
          </div>
        </div>
      )}
    </div>
  );
}
