import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { LoaderCircle, Pause, Play, RefreshCw, Square, Trash2 } from 'lucide-react';
import { toast } from 'sonner';

import { BatchIdCombobox, type BatchIdComboboxOption } from '@/components/shared/BatchIdCombobox';
import { DataTable, type Column } from '@/components/shared/DataTable';
import { searchFieldClassName } from '@/components/shared/searchFieldStyles';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Progress } from '@/components/ui/progress';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Separator } from '@/components/ui/separator';
import { Skeleton } from '@/components/ui/skeleton';
import {
  deleteSearchTask,
  fetchSearchStatus,
  fetchSearchTasks,
  pauseSearchBatch,
  resumeSearchBatch,
  stopSearchBatch,
  type SearchProgress,
  type SearchTaskListItem,
  type SearchTaskStatus,
  type SearchTaskListSummary,
} from '@/services/automationService';
import { formatDate } from '@/lib/dateUtils';
import { useSearchManualIntervention } from '@/contexts/SearchManualInterventionContext';
import { playAlertSound } from '@/lib/manualInterventionAlertSounds';

interface SearchTaskStatusPanelProps {
  active: boolean;
  batchOptions: BatchIdComboboxOption[];
  initialBatchId?: string;
  onBatchIdChange?: (batchId: string) => void;
}

const EMPTY_SUMMARY: SearchTaskListSummary = {
  total: 0,
  pending: 0,
  processing: 0,
  waiting_for_manual: 0,
  pausing: 0,
  paused: 0,
  stopping: 0,
  stopped: 0,
  completed: 0,
  failed: 0,
};

function renderTaskStatusBadge(status: SearchTaskStatus) {
  const statusConfig: Record<SearchTaskStatus, { label: string; className: string }> = {
    idle: { label: '空闲', className: 'border-slate-200 bg-slate-50 text-slate-600' },
    pending: { label: '待执行', className: 'border-slate-200 bg-slate-50 text-slate-700' },
    processing: { label: '执行中', className: 'border-blue-200 bg-blue-50 text-blue-700' },
    waiting_for_manual: { label: '等待人工', className: 'border-orange-200 bg-orange-50 text-orange-700' },
    pausing: { label: '暂停中', className: 'border-amber-200 bg-amber-50 text-amber-700' },
    paused: { label: '已暂停', className: 'border-amber-200 bg-amber-50 text-amber-700' },
    stopping: { label: '结束中', className: 'border-rose-200 bg-rose-50 text-rose-700' },
    stopped: { label: '已结束', className: 'border-slate-200 bg-slate-100 text-slate-700' },
    completed: { label: '已完成', className: 'border-emerald-200 bg-emerald-50 text-emerald-700' },
    failed: { label: '失败', className: 'border-rose-200 bg-rose-50 text-rose-700' },
  };

  const config = statusConfig[status];
  return <Badge variant="outline" className={config.className}>{config.label}</Badge>;
}

function getProgressPercent(task: Pick<SearchTaskListItem, 'processed_rows' | 'total_rows' | 'display_progress_percent'>) {
  if (typeof task.display_progress_percent === 'number') {
    return Math.min(100, Math.max(0, Math.round(task.display_progress_percent)));
  }

  if (task.total_rows <= 0) {
    return 0;
  }

  return Math.min(100, Math.round((task.processed_rows / task.total_rows) * 100));
}

function getSmoothSearchProgressPercent(params: {
  status: SearchTaskStatus;
  basePercent: number;
  totalRows: number;
  processedRows: number;
  searchProgress?: SearchProgress['searchProgress'];
}) {
  const basePercent = Math.min(100, Math.max(0, Math.round(params.basePercent)));
  if (
    params.status !== 'processing'
    || !params.searchProgress
    || typeof params.searchProgress.softCapPercent !== 'number'
    || !params.searchProgress.stageStartedAt
    || params.totalRows <= 0
  ) {
    return basePercent;
  }

  const startedAt = Date.parse(params.searchProgress.stageStartedAt);
  if (Number.isNaN(startedAt)) {
    return basePercent;
  }

  const elapsedSeconds = Math.max(0, (Date.now() - startedAt) / 1000);
  const itemProgress = Math.max(0, Number(params.searchProgress.itemProgressPercent ?? 0));
  const softCap = Math.max(itemProgress, Number(params.searchProgress.softCapPercent));
  const animatedItemProgress = Math.min(softCap, itemProgress + elapsedSeconds * 1.2);
  const animatedOverall = Math.round(((params.processedRows + animatedItemProgress / 100) / params.totalRows) * 100);
  return Math.max(basePercent, Math.min(100, animatedOverall));
}

function useSmoothSearchProgressPercent(params: {
  status: SearchTaskStatus;
  basePercent: number;
  totalRows: number;
  processedRows: number;
  searchProgress?: SearchProgress['searchProgress'];
}) {
  const [, setTick] = useState(0);

  useEffect(() => {
    if (
      params.status !== 'processing'
      || !params.searchProgress?.stageStartedAt
      || typeof params.searchProgress.softCapPercent !== 'number'
    ) {
      return;
    }

    const timer = window.setInterval(() => setTick((value) => value + 1), 1000);
    return () => window.clearInterval(timer);
  }, [params.searchProgress?.softCapPercent, params.searchProgress?.stageStartedAt, params.status]);

  return getSmoothSearchProgressPercent(params);
}

function SearchTaskProgressCell({ task }: { task: SearchTaskListItem }) {
  const basePercent = getProgressPercent(task);
  const percent = useSmoothSearchProgressPercent({
    status: task.status,
    basePercent,
    totalRows: task.total_rows,
    processedRows: task.processed_rows,
    searchProgress: task.search_progress,
  });

  return (
    <div className="space-y-1">
      <div className="flex items-center justify-between text-xs text-muted-foreground">
        <span>{task.processed_rows} / {task.total_rows}</span>
        <span>{percent}%</span>
      </div>
      <Progress value={percent} className="h-1.5" />
    </div>
  );
}

function canPauseTask(task: SearchTaskListItem) {
  return task.status === 'processing' || task.status === 'waiting_for_manual';
}

function canResumeTask(task: SearchTaskListItem) {
  return task.status === 'paused';
}

function canStopTask(task: SearchTaskListItem) {
  return task.status === 'pending'
    || task.status === 'processing'
    || task.status === 'waiting_for_manual'
    || task.status === 'pausing'
    || task.status === 'paused'
    || task.status === 'stopping';
}

const FAILURE_SOUND_OPTION = { id: 'failure', label: '失败提示音', src: '/sounds/manual-intervention-library/alert-15.mp3' };

export function SearchTaskStatusPanel({
  active,
  batchOptions,
  initialBatchId = '',
  onBatchIdChange,
}: SearchTaskStatusPanelProps) {
  const { previewSelectedSound } = useSearchManualIntervention();
  const [batchId, setBatchId] = useState(initialBatchId);
  const [status, setStatus] = useState<'all' | SearchTaskStatus>('all');
  const [accountId, setAccountId] = useState('all');
  const [search, setSearch] = useState('');
  const [loading, setLoading] = useState(true);
  const [tasks, setTasks] = useState<SearchTaskListItem[]>([]);
  const [summary, setSummary] = useState<SearchTaskListSummary>(EMPTY_SUMMARY);
  const [selectedTaskId, setSelectedTaskId] = useState<string | null>(null);
  const [selectedTaskDetail, setSelectedTaskDetail] = useState<SearchProgress | null>(null);
  const [detailLoading, setDetailLoading] = useState(false);
  const [actionTaskId, setActionTaskId] = useState<string | null>(null);
  const [actionType, setActionType] = useState<'pause' | 'resume' | 'stop' | 'delete' | null>(null);
  const selectedTaskIdRef = useRef<string | null>(null);
  const previousTaskStatusesRef = useRef<Record<string, string>>({});
  const failureAudioRef = useRef<HTMLAudioElement | null>(null);;

  useEffect(() => {
    setBatchId(initialBatchId);
  }, [initialBatchId]);

  useEffect(() => {
    selectedTaskIdRef.current = selectedTaskId;
  }, [selectedTaskId]);

  const openTaskDetail = useCallback((taskId: string) => {
    selectedTaskIdRef.current = taskId;
    setSelectedTaskId(taskId);
    setSelectedTaskDetail(null);
    setDetailLoading(true);
  }, []);

  const closeTaskDetail = useCallback(() => {
    selectedTaskIdRef.current = null;
    setSelectedTaskId(null);
    setSelectedTaskDetail(null);
    setDetailLoading(false);
  }, []);

  const loadTasks = useCallback(async (showSkeleton = false) => {
    try {
      if (showSkeleton) {
        setLoading(true);
      }

      const result = await fetchSearchTasks({
        batchId: batchId || undefined,
        accountId: accountId === 'all' ? undefined : accountId,
        statuses: status === 'all' ? undefined : [status],
        search: search || undefined,
        limit: 200,
      });

      setTasks(result.tasks);
      setSummary(result.summary);
    } catch (error) {
      if (showSkeleton) {
        toast.error(`读取搜索任务失败: ${error instanceof Error ? error.message : String(error)}`);
      }
    } finally {
      if (showSkeleton) {
        setLoading(false);
      }
    }
  }, [accountId, batchId, search, status]);

  const loadTaskDetail = useCallback(async (taskId: string, showSkeleton = false) => {
    try {
      if (showSkeleton && selectedTaskIdRef.current === taskId) {
        setDetailLoading(true);
      }

      const detail = await fetchSearchStatus(taskId);
      if (selectedTaskIdRef.current === taskId) {
        setSelectedTaskDetail(detail);
      }
    } catch (error) {
      if (showSkeleton && selectedTaskIdRef.current === taskId) {
        toast.error(`读取任务详情失败: ${error instanceof Error ? error.message : String(error)}`);
      }
    } finally {
      if (showSkeleton && selectedTaskIdRef.current === taskId) {
        setDetailLoading(false);
      }
    }
  }, []);

  useEffect(() => {
    if (!active) {
      return;
    }

    void loadTasks(true);
    const timer = window.setInterval(() => {
      void loadTasks(false);
    }, 2000);

    return () => {
      window.clearInterval(timer);
    };
  }, [active, loadTasks]);

  useEffect(() => {
    const prev = previousTaskStatusesRef.current;
    const activeStatuses = new Set(['pending', 'processing', 'waiting_for_manual', 'pausing', 'paused', 'stopping']);
    const hasNewlyCompleted = tasks.some(
      (task) => task.status === 'completed' && activeStatuses.has(prev[task.id] ?? ''),
    );
    const hasNewlyFailed = tasks.some(
      (task) => task.status === 'failed' && activeStatuses.has(prev[task.id] ?? ''),
    );
    previousTaskStatusesRef.current = Object.fromEntries(tasks.map((task) => [task.id, task.status]));
    if (hasNewlyCompleted) {
      void previewSelectedSound();
    }
    if (hasNewlyFailed) {
      void playAlertSound(failureAudioRef, FAILURE_SOUND_OPTION);
    }
  }, [tasks, previewSelectedSound]);

  useEffect(() => {
    if (selectedTaskId && !tasks.some((task) => task.id === selectedTaskId)) {
      closeTaskDetail();
    }
  }, [closeTaskDetail, tasks, selectedTaskId]);

  useEffect(() => {
    if (!active || !selectedTaskId) {
      return;
    }

    void loadTaskDetail(selectedTaskId, true);
    const timer = window.setInterval(() => {
      void loadTaskDetail(selectedTaskId, false);
    }, 2000);

    return () => {
      window.clearInterval(timer);
    };
  }, [active, loadTaskDetail, selectedTaskId]);

  const selectedTask = useMemo(
    () => tasks.find((task) => task.id === selectedTaskId) ?? null,
    [tasks, selectedTaskId],
  );

  const selectedTaskKeys = useMemo(
    () => (selectedTaskId ? new Set([selectedTaskId]) : new Set<string>()),
    [selectedTaskId],
  );

  const accountOptions = useMemo(() => {
    const optionMap = new Map<string, string>();
    tasks.forEach((task) => {
      if (task.account_id) {
        optionMap.set(task.account_id, task.account_name || task.account_id);
      }
    });

    return [...optionMap.entries()].map(([id, label]) => ({ id, label }));
  }, [tasks]);

  const handlePause = useCallback(async (taskId: string) => {
    setActionTaskId(taskId);
    setActionType('pause');
    try {
      const result = await pauseSearchBatch(taskId);
      toast.success(result.message || '搜索任务已暂停');
      await loadTasks(false);
      if (selectedTaskId === taskId) {
        await loadTaskDetail(taskId, false);
      }
    } catch (error) {
      toast.error(`暂停失败: ${error instanceof Error ? error.message : String(error)}`);
    } finally {
      setActionTaskId(null);
      setActionType(null);
    }
  }, [loadTaskDetail, loadTasks, selectedTaskId]);

  const handleResume = useCallback(async (taskId: string) => {
    setActionTaskId(taskId);
    setActionType('resume');
    try {
      const result = await resumeSearchBatch(taskId);
      toast.success(result.message || '搜索任务恢复中');
      await loadTasks(false);
      if (selectedTaskId === taskId) {
        await loadTaskDetail(taskId, false);
      }
    } catch (error) {
      toast.error(`恢复失败: ${error instanceof Error ? error.message : String(error)}`);
    } finally {
      setActionTaskId(null);
      setActionType(null);
    }
  }, [loadTaskDetail, loadTasks, selectedTaskId]);

  const handleStop = useCallback(async (taskId: string) => {
    setActionTaskId(taskId);
    setActionType('stop');
    try {
      const result = await stopSearchBatch(taskId);
      toast.success(result.message || '搜索任务结束中');
      await loadTasks(false);
      if (selectedTaskId === taskId) {
        await loadTaskDetail(taskId, false);
      }
    } catch (error) {
      toast.error(`结束失败: ${error instanceof Error ? error.message : String(error)}`);
    } finally {
      setActionTaskId(null);
      setActionType(null);
    }
  }, [loadTaskDetail, loadTasks, selectedTaskId]);

  const handleDelete = useCallback(async (taskId: string) => {
    setActionTaskId(taskId);
    setActionType('delete');
    try {
      const result = await deleteSearchTask(taskId);
      toast.success(result.message || '搜索任务记录已删除');
      if (selectedTaskId === taskId) {
        closeTaskDetail();
      }
      await loadTasks(false);
    } catch (error) {
      toast.error(`删除失败: ${error instanceof Error ? error.message : String(error)}`);
    } finally {
      setActionTaskId(null);
      setActionType(null);
    }
  }, [closeTaskDetail, loadTasks, selectedTaskId]);

  const dialogTaskStatus = selectedTaskDetail?.status ?? selectedTask?.status ?? 'idle';
  const dialogProgressProcessedRows = selectedTaskDetail?.processedRows ?? selectedTask?.processed_rows ?? 0;
  const dialogProgressTotalRows = selectedTaskDetail?.totalRows ?? selectedTask?.total_rows ?? 0;
  const dialogBaseProgressPercent = selectedTaskDetail?.displayProgressPercent ?? selectedTask?.display_progress_percent ?? (
    dialogProgressTotalRows > 0
      ? Math.min(100, Math.round((dialogProgressProcessedRows / dialogProgressTotalRows) * 100))
      : 0
  );
  const dialogProgressPercent = useSmoothSearchProgressPercent({
    status: dialogTaskStatus,
    basePercent: dialogBaseProgressPercent,
    totalRows: dialogProgressTotalRows,
    processedRows: dialogProgressProcessedRows,
    searchProgress: selectedTaskDetail?.searchProgress ?? selectedTask?.search_progress,
  });
  const dialogCurrentItem = selectedTaskDetail?.currentStepLabel || selectedTask?.current_step_label || selectedTaskDetail?.currentItem || selectedTask?.current_item || '-';
  const dialogCurrentRow = selectedTaskDetail?.currentRow || selectedTask?.current_material_id || '';
  const dialogErrors = selectedTaskDetail?.errors && selectedTaskDetail.errors.length > 0
    ? selectedTaskDetail.errors
    : selectedTask?.errors && selectedTask.errors.length > 0
      ? selectedTask.errors
      : selectedTask?.error_message
      ? [selectedTask.error_message]
      : [];
  const dialogShortage = selectedTaskDetail?.result?.searchShortage;
  const dialogArtifacts = selectedTaskDetail?.result?.searchArtifacts;

  const columns = useMemo<Column<SearchTaskListItem>[]>(() => [
    { key: 'status', label: '任务状态', defaultWidth: 96, render: (value) => renderTaskStatusBadge(value as SearchTaskStatus) },
    { key: 'batch_id', label: '批次ID', defaultWidth: 170, render: (value) => <span className="font-mono text-xs text-muted-foreground whitespace-nowrap">{String(value)}</span> },
    { key: 'material_name', label: '材料名称', defaultWidth: 170, truncate: true },
    { key: 'account_name', label: '执行账户', defaultWidth: 120, truncate: true, render: (value, row) => (value as string) || row.account_id },
    {
      key: 'processed_rows',
      label: '进度',
      defaultWidth: 180,
      render: (_value, row) => {
        return <SearchTaskProgressCell task={row} />;
      },
    },
    { key: 'current_item', label: '当前步骤', defaultWidth: 260, truncate: true, render: (_value, row) => row.current_step_label || row.current_item },
    { key: 'updated_at', label: '更新时间', sortable: true, defaultWidth: 148, render: (value) => value ? formatDate(value as string) : '-' },
    {
      key: '_actions',
      label: '操作',
      defaultWidth: 260,
      render: (_value, row) => {
        const actionLoading = actionTaskId === row.id;
        const toggleAction = canPauseTask(row)
          ? {
              action: 'pause' as const,
              label: '暂停',
              className: 'text-xs text-amber-600 hover:text-amber-700',
              icon: Pause,
              onClick: () => {
                void handlePause(row.id);
              },
            }
          : canResumeTask(row)
            ? {
                action: 'resume' as const,
                label: '启动',
                className: 'text-xs text-emerald-600 hover:text-emerald-700',
                icon: Play,
                onClick: () => {
                  void handleResume(row.id);
                },
              }
            : null;
        const stopActionAvailable = canStopTask(row);

        return (
          <div className="flex w-full items-center justify-between gap-1 whitespace-nowrap">
            <Button
              variant="ghost"
              size="sm"
              className="h-8 px-2 text-xs text-blue-600 hover:text-blue-700"
              onClick={(event) => {
                event.stopPropagation();
                openTaskDetail(row.id);
              }}
            >
              详情
            </Button>
            {toggleAction ? (
              <Button
                variant="ghost"
                size="sm"
                className={`h-8 px-2 text-xs ${toggleAction.className}`}
                disabled={actionLoading}
                onClick={(event) => {
                  event.stopPropagation();
                  toggleAction.onClick();
                }}
              >
                {actionLoading && actionType === toggleAction.action
                  ? <LoaderCircle className="mr-1 h-3.5 w-3.5 animate-spin" />
                  : <toggleAction.icon className="mr-1 h-3.5 w-3.5" />}
                {toggleAction.label}
              </Button>
            ) : (
              <Button
                variant="ghost"
                size="sm"
                className="h-8 px-2 text-xs text-muted-foreground"
                disabled
                onClick={(event) => {
                  event.stopPropagation();
                }}
              >
                <Pause className="mr-1 h-3.5 w-3.5" />
                暂停
              </Button>
            )}
            {stopActionAvailable ? (
              <Button
                variant="ghost"
                size="sm"
                className="h-8 px-2 text-xs text-rose-600 hover:text-rose-700"
                disabled={actionLoading}
                onClick={(event) => {
                  event.stopPropagation();
                  void handleStop(row.id);
                }}
              >
                {actionLoading && actionType === 'stop' ? <LoaderCircle className="mr-1 h-3.5 w-3.5 animate-spin" /> : <Square className="mr-1 h-3.5 w-3.5" />}
                结束
              </Button>
            ) : null}
            {row.deletable ? (
              <Button
                variant="ghost"
                size="sm"
                className="h-8 px-2 text-xs text-slate-600 hover:text-slate-800"
                disabled={actionLoading}
                onClick={(event) => {
                  event.stopPropagation();
                  void handleDelete(row.id);
                }}
              >
                {actionLoading && actionType === 'delete' ? <LoaderCircle className="mr-1 h-3.5 w-3.5 animate-spin" /> : <Trash2 className="mr-1 h-3.5 w-3.5" />}
                删除
              </Button>
            ) : null}
          </div>
        );
      },
    },
  ], [actionTaskId, actionType, handleDelete, handlePause, handleResume, handleStop, openTaskDetail]);

  return (
    <div className="h-full flex flex-col">
      <div className="mb-3 shrink-0 w-full">
        <div className="grid grid-cols-[max-content_10rem_max-content_10rem_max-content_10rem_max-content_16rem] gap-x-3 gap-y-2 items-center flex-none">
          <span className="text-sm text-muted-foreground">批次ID</span>
          <BatchIdCombobox
            value={batchId}
            onChange={(value) => {
              const nextValue = value || '';
              setBatchId(nextValue);
              onBatchIdChange?.(nextValue);
            }}
            options={batchOptions}
            className="w-40"
          />
          <span className="text-sm text-muted-foreground pl-4">任务状态</span>
          <Select value={status} onValueChange={(value) => setStatus(value as 'all' | SearchTaskStatus)}>
            <SelectTrigger className={`w-40 ${searchFieldClassName}`}>
              <SelectValue placeholder="全部状态" />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="all">全部状态</SelectItem>
              <SelectItem value="pending">待执行</SelectItem>
              <SelectItem value="processing">执行中</SelectItem>
              <SelectItem value="waiting_for_manual">等待人工</SelectItem>
              <SelectItem value="pausing">暂停中</SelectItem>
              <SelectItem value="paused">已暂停</SelectItem>
              <SelectItem value="stopping">结束中</SelectItem>
              <SelectItem value="stopped">已结束</SelectItem>
              <SelectItem value="completed">已完成</SelectItem>
              <SelectItem value="failed">失败</SelectItem>
            </SelectContent>
          </Select>
          <span className="text-sm text-muted-foreground pl-4">执行账户</span>
          <Select value={accountId} onValueChange={setAccountId}>
            <SelectTrigger className={`w-40 ${searchFieldClassName}`}>
              <SelectValue placeholder="全部账户" />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="all">全部账户</SelectItem>
              {accountOptions.map((option) => (
                <SelectItem key={option.id} value={option.id}>{option.label}</SelectItem>
              ))}
            </SelectContent>
          </Select>
          <span className="text-sm text-muted-foreground pl-4">搜索</span>
          <Input
            placeholder="任务ID / 批次ID / 材料名称 / 当前步骤"
            value={search}
            onChange={(event) => setSearch(event.target.value)}
            className={searchFieldClassName}
          />
        </div>
      </div>

      <Separator className="mb-3 shrink-0" />

      <div className="mb-3 shrink-0 flex flex-wrap items-center gap-2">
        <Badge variant="outline">总任务 {summary.total}</Badge>
        <Badge variant="outline">待执行 {summary.pending}</Badge>
        <Badge variant="outline">执行中 {summary.processing}</Badge>
        <Badge variant="outline">等待人工 {summary.waiting_for_manual}</Badge>
        <Badge variant="outline">暂停中 {summary.pausing}</Badge>
        <Badge variant="outline">已暂停 {summary.paused}</Badge>
        <Badge variant="outline">结束中 {summary.stopping}</Badge>
        <Badge variant="outline">已结束 {summary.stopped}</Badge>
        <Badge variant="outline">已完成 {summary.completed}</Badge>
        <Badge variant="outline">失败 {summary.failed}</Badge>
        <Button variant="outline" size="sm" className="ml-auto h-9" onClick={() => void loadTasks(true)}>
          <RefreshCw className="mr-1 h-3.5 w-3.5" />刷新
        </Button>
      </div>

      {loading ? (
        <div className="space-y-3">
          {Array.from({ length: 5 }).map((_, index) => <Skeleton key={index} className="h-10 w-full" />)}
        </div>
      ) : (
        <div className="flex-1 min-h-0 overflow-auto pr-1">
          <DataTable
            columns={columns}
            data={tasks}
            loading={false}
            rowKey={(row) => row.id}
            selectedKeys={selectedTaskKeys}
            onRowClick={(row) => openTaskDetail(row.id)}
            showRowIndex
          />
        </div>
      )}

      {!loading && tasks.length === 0 ? (
        <div className="mt-4 rounded-lg border border-dashed p-6 text-center text-sm text-muted-foreground">
          当前筛选条件下暂无搜索任务。
        </div>
      ) : null}

      <Dialog open={Boolean(selectedTaskId)} onOpenChange={(open) => { if (!open) closeTaskDetail(); }}>
        <DialogContent className="max-w-4xl max-h-[85vh] overflow-y-auto">
          <DialogHeader>
            <DialogTitle>任务详情</DialogTitle>
            <DialogDescription>
              {selectedTask ? `任务 ID：${selectedTask.id}` : '查看搜索任务的实时状态与结果摘要。'}
            </DialogDescription>
          </DialogHeader>
          {!selectedTask ? (
            <div className="rounded-md border border-dashed p-4 text-sm text-muted-foreground">
              当前任务不存在或已被当前筛选条件隐藏。
            </div>
          ) : detailLoading && !selectedTaskDetail ? (
            <div className="space-y-3">
              <Skeleton className="h-10 w-full" />
              <Skeleton className="h-24 w-full" />
              <Skeleton className="h-24 w-full" />
            </div>
          ) : (
            <div className="space-y-4">
              <div className="grid gap-3 md:grid-cols-3">
                <div className="rounded-md border p-3">
                  <div className="text-xs text-muted-foreground">任务状态</div>
                  <div className="mt-2 flex items-center gap-2">
                    {renderTaskStatusBadge(dialogTaskStatus)}
                  </div>
                </div>
                <div className="rounded-md border p-3">
                  <div className="text-xs text-muted-foreground">当前进度</div>
                  <div className="mt-2 text-sm font-medium">{dialogProgressProcessedRows} / {dialogProgressTotalRows}</div>
                  <Progress value={dialogProgressPercent} className="mt-2 h-2" />
                </div>
                <div className="rounded-md border p-3">
                  <div className="text-xs text-muted-foreground">最近更新时间</div>
                  <div className="mt-2 text-sm font-medium">{selectedTask.updated_at ? formatDate(selectedTask.updated_at) : '-'}</div>
                </div>
              </div>

              <div className="grid gap-3 md:grid-cols-2 xl:grid-cols-4">
                <div>
                  <div className="text-xs text-muted-foreground">批次ID</div>
                  <div className="mt-1 font-mono text-xs text-foreground break-all">{selectedTask.batch_id}</div>
                </div>
                <div>
                  <div className="text-xs text-muted-foreground">执行账户</div>
                  <div className="mt-1 text-sm text-foreground">{selectedTask.account_name || selectedTask.account_id || '-'}</div>
                </div>
                <div>
                  <div className="text-xs text-muted-foreground">材料名称</div>
                  <div className="mt-1 text-sm text-foreground">{selectedTask.material_name || '-'}</div>
                </div>
                <div>
                  <div className="text-xs text-muted-foreground">材料ID</div>
                  <div className="mt-1 font-mono text-xs text-foreground break-all">{selectedTask.material_id || '-'}</div>
                </div>
              </div>

              <div className="rounded-md border p-3">
                <div className="text-xs text-muted-foreground">当前步骤</div>
                <div className="mt-1 text-sm font-medium text-foreground">{dialogCurrentItem}</div>
                {dialogCurrentRow ? (
                  <div className="mt-1 font-mono text-xs text-muted-foreground">material_id: {dialogCurrentRow}</div>
                ) : null}
              </div>

              {dialogErrors.length > 0 ? (
                <div className="rounded-md border border-rose-200 bg-rose-50 p-3">
                  <div className="text-sm font-medium text-rose-700">错误信息</div>
                  <div className="mt-2 space-y-1 text-xs text-rose-700">
                    {dialogErrors.map((error, index) => (
                      <p key={`${selectedTask.id}-error-${index}`}>{error}</p>
                    ))}
                  </div>
                </div>
              ) : (
                <div className="rounded-md border p-3 text-sm text-muted-foreground">
                  暂无错误信息
                </div>
              )}

              <div className="flex flex-wrap gap-2">
                {canPauseTask(selectedTask) ? (
                  <Button variant="outline" size="sm" onClick={() => void handlePause(selectedTask.id)} disabled={actionTaskId === selectedTask.id}>
                    {actionTaskId === selectedTask.id && actionType === 'pause' ? <LoaderCircle className="mr-1 h-3.5 w-3.5 animate-spin" /> : <Pause className="mr-1 h-3.5 w-3.5" />}
                    暂停任务
                  </Button>
                ) : null}
                {canResumeTask(selectedTask) ? (
                  <Button variant="outline" size="sm" onClick={() => void handleResume(selectedTask.id)} disabled={actionTaskId === selectedTask.id}>
                    {actionTaskId === selectedTask.id && actionType === 'resume' ? <LoaderCircle className="mr-1 h-3.5 w-3.5 animate-spin" /> : <Play className="mr-1 h-3.5 w-3.5" />}
                    启动任务
                  </Button>
                ) : null}
                {canStopTask(selectedTask) ? (
                  <Button variant="destructive" size="sm" onClick={() => void handleStop(selectedTask.id)} disabled={actionTaskId === selectedTask.id}>
                    {actionTaskId === selectedTask.id && actionType === 'stop' ? <LoaderCircle className="mr-1 h-3.5 w-3.5 animate-spin" /> : <Square className="mr-1 h-3.5 w-3.5" />}
                    结束任务
                  </Button>
                ) : null}
                {selectedTask.deletable ? (
                  <Button variant="outline" size="sm" onClick={() => void handleDelete(selectedTask.id)} disabled={actionTaskId === selectedTask.id}>
                    {actionTaskId === selectedTask.id && actionType === 'delete' ? <LoaderCircle className="mr-1 h-3.5 w-3.5 animate-spin" /> : <Trash2 className="mr-1 h-3.5 w-3.5" />}
                    删除记录
                  </Button>
                ) : null}
              </div>

              <div className="rounded-md border p-3">
                <div className="text-sm font-medium text-foreground">结果摘要</div>
                <div className="mt-2 grid gap-2 md:grid-cols-4 text-sm">
                  <div><span className="text-muted-foreground">已处理：</span>{selectedTaskDetail?.result?.processedRows ?? dialogProgressProcessedRows}</div>
                  <div><span className="text-muted-foreground">完成：</span>{selectedTaskDetail?.result?.completedRows ?? selectedTask.completed_rows}</div>
                  <div><span className="text-muted-foreground">失败：</span>{selectedTaskDetail?.result?.failedRows ?? selectedTask.failed_rows}</div>
                  <div><span className="text-muted-foreground">结束：</span>{selectedTaskDetail?.result?.stoppedRows ?? selectedTask.stopped_rows}</div>
                </div>
                {dialogShortage?.message ? (
                  <div className="mt-3 rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-800">
                    {dialogShortage.message}
                  </div>
                ) : null}
                {dialogArtifacts ? (
                  <div className="mt-3 space-y-1 border-t pt-3 text-xs text-muted-foreground">
                    <div>LLM JSON：{dialogArtifacts.llmMatchResults?.length ?? 0} 个 · 联系方式审计：{dialogArtifacts.contactEnrichmentResults?.length ?? 0} 个</div>
                    {dialogArtifacts.llmMatchResults?.[0] ? (
                      <div className="break-all">LLM：{dialogArtifacts.llmMatchResults[0]}</div>
                    ) : null}
                    {dialogArtifacts.llmBatchRecords?.[0] ? (
                      <div className="break-all">Batch：{dialogArtifacts.llmBatchRecords[0]}</div>
                    ) : null}
                    {dialogArtifacts.llmBatchErrors?.[0] ? (
                      <div className="break-all">Batch错误：{dialogArtifacts.llmBatchErrors[0]}</div>
                    ) : null}
                    {dialogArtifacts.contactEnrichmentResults?.[0] ? (
                      <div className="break-all">补齐审计：{dialogArtifacts.contactEnrichmentResults[0]}</div>
                    ) : null}
                    {dialogArtifacts.outputRoot ? (
                      <div className="break-all">输出目录：{dialogArtifacts.outputRoot}</div>
                    ) : null}
                  </div>
                ) : null}
              </div>
            </div>
          )}
        </DialogContent>
      </Dialog>
    </div>
  );
}
