import { useState, useEffect, useRef } from 'react';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogDescription } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Progress } from '@/components/ui/progress';
import { LoaderCircle, Pause, Play, Square, CheckCircle2, XCircle, AlertTriangle } from 'lucide-react';
import {
  fetchSearchStatus,
  pauseSearchBatch,
  resumeSearchBatch,
  stopSearchBatch,
  type SearchStageTiming,
  type SearchProgress,
} from '@/services/automationService';
import { buildSearchDisplayErrors, summarizeSearchProgressMessage } from '@/components/shared/searchProgressDialogUtils';
import { toast } from 'sonner';

interface SearchProgressDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  taskId?: string | null;
  onTaskIdChange?: (taskId: string | null) => void;
}

function getSmoothSearchProgressPercent(progress: SearchProgress | null, basePercent: number) {
  if (
    !progress
    || progress.status !== 'processing'
    || !progress.searchProgress
    || typeof progress.searchProgress.softCapPercent !== 'number'
    || !progress.searchProgress.stageStartedAt
    || progress.totalRows <= 0
  ) {
    return basePercent;
  }

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

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

function useSmoothSearchProgressPercent(progress: SearchProgress | null, basePercent: number) {
  const [, setTick] = useState(0);

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

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

  return getSmoothSearchProgressPercent(progress, basePercent);
}

function manualInterventionTitle(kind?: string) {
  return kind === 'sms_verification' ? '等待人工处理手机短信验证码' : '等待人工处理验证码';
}

function formatDurationMs(value: number | null | undefined) {
  if (value == null || !Number.isFinite(value) || value < 0) return '-';
  const totalSeconds = Math.floor(value / 1000);
  const minutes = Math.floor(totalSeconds / 60);
  const seconds = totalSeconds % 60;
  return minutes > 0 ? `${minutes}分${String(seconds).padStart(2, '0')}秒` : `${seconds}秒`;
}

function stageTitle(stage: SearchStageTiming) {
  const prefix = stage.stageOrder != null ? `阶段 ${stage.stageOrder}` : '当前阶段';
  return `${prefix}${stage.stageLabel ? ` · ${stage.stageLabel}` : ''}`;
}

export function SearchProgressDialog({ open, onOpenChange, taskId, onTaskIdChange }: SearchProgressDialogProps) {
  const [progress, setProgress] = useState<SearchProgress | null>(null);
  const [action, setAction] = useState<'pause' | 'resume' | 'stop' | null>(null);
  const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);

  useEffect(() => {
    async function loadProgress() {
      try {
        const next = await fetchSearchStatus(taskId ?? undefined);
        setProgress(next);
        if (next.taskId && next.taskId !== taskId) {
          onTaskIdChange?.(next.taskId);
        }
      } catch {
        // ignore polling errors in dialog
      }
    }

    if (open) {
      void loadProgress();
      intervalRef.current = setInterval(() => {
        void loadProgress();
      }, 2000);
    }

    return () => {
      if (intervalRef.current) {
        clearInterval(intervalRef.current);
        intervalRef.current = null;
      }
    };
  }, [open, taskId, onTaskIdChange]);

  const status = progress?.status;

  useEffect(() => {
    if (status && ['completed', 'failed', 'stopped'].includes(status)) {
      if (intervalRef.current) {
        clearInterval(intervalRef.current);
        intervalRef.current = null;
      }
    }
  }, [status]);

  async function refreshProgress() {
    try {
      const next = await fetchSearchStatus(taskId ?? undefined);
      setProgress(next);
      if (next.taskId && next.taskId !== taskId) {
        onTaskIdChange?.(next.taskId);
      }
    } catch {
      // ignore action refresh errors in dialog
    }
  }

  async function handlePause() {
    setAction('pause');
    try {
      const result = await pauseSearchBatch(progress?.taskId || taskId || undefined);
      toast.info(result.message || '暂停信号已发送');
      if (result.taskId) {
        onTaskIdChange?.(result.taskId);
      }
      await refreshProgress();
    } catch (err) {
      toast.error(`暂停失败: ${err instanceof Error ? err.message : String(err)}`);
    } finally {
      setAction(null);
    }
  }

  async function handleResume() {
    setAction('resume');
    try {
      const result = await resumeSearchBatch(progress?.taskId || taskId || undefined);
      toast.success(result.message || '搜索任务恢复中');
      if (result.taskId) {
        onTaskIdChange?.(result.taskId);
      }
      await refreshProgress();
    } catch (err) {
      toast.error(`恢复失败: ${err instanceof Error ? err.message : String(err)}`);
    } finally {
      setAction(null);
    }
  }

  async function handleStop() {
    setAction('stop');
    try {
      const result = await stopSearchBatch(progress?.taskId || taskId || undefined);
      toast.info(result.message || '停止信号已发送');
      if (result.taskId) {
        onTaskIdChange?.(result.taskId);
      }
      await refreshProgress();
    } catch (err) {
      toast.error(`停止失败: ${err instanceof Error ? err.message : String(err)}`);
    } finally {
      setAction(null);
    }
  }

  const isProcessing = progress?.status === 'processing';
  const isWaitingForManual = progress?.status === 'waiting_for_manual';
  const isPausing = progress?.status === 'pausing';
  const isPaused = progress?.status === 'paused';
  const isStopping = progress?.status === 'stopping';
  const canPause = isProcessing || isWaitingForManual;
  const isTerminal = progress ? ['completed', 'failed', 'stopped'].includes(progress.status) : false;
  const showSummary = Boolean(progress?.result) && (isTerminal || isPaused);
  const displayErrors = buildSearchDisplayErrors(progress?.errors, progress?.result?.error);
  const resultError = summarizeSearchProgressMessage(progress?.result?.error);
  const manualIntervention = progress?.result?.manualIntervention;
  const searchShortage = progress?.result?.searchShortage;
  const searchArtifacts = progress?.result?.searchArtifacts;
  const stageTiming = progress?.stageTiming ?? progress?.result?.stageTiming;
  const currentStage = stageTiming?.currentStage;
  const completedStages = stageTiming?.completedStages ?? [];
  const hasVisibleTask = Boolean(progress?.taskId);
  const basePercentage = progress?.displayProgressPercent != null
    ? Math.min(100, Math.max(0, Math.round(progress.displayProgressPercent)))
    : progress && progress.totalRows > 0
      ? Math.round((progress.processedRows / progress.totalRows) * 100)
      : 0;
  const percentage = useSmoothSearchProgressPercent(progress, basePercentage);
  const currentStepLabel = progress?.currentStepLabel || progress?.currentItem;

  function statusIcon() {
    if (!progress) return <LoaderCircle className="h-5 w-5 animate-spin text-muted-foreground" />;
    switch (progress.status) {
      case 'processing': return <LoaderCircle className="h-5 w-5 animate-spin text-blue-500" />;
      case 'waiting_for_manual': return <AlertTriangle className="h-5 w-5 text-orange-500" />;
      case 'pausing': return <AlertTriangle className="h-5 w-5 text-amber-500" />;
      case 'paused': return <Pause className="h-5 w-5 text-amber-500" />;
      case 'stopping': return <AlertTriangle className="h-5 w-5 text-red-500" />;
      case 'stopped': return <Square className="h-5 w-5 text-slate-500" />;
      case 'completed': return <CheckCircle2 className="h-5 w-5 text-green-500" />;
      case 'failed': return <XCircle className="h-5 w-5 text-destructive" />;
      default: return null;
    }
  }

  function statusLabel() {
    if (!progress) return '加载中...';
    switch (progress.status) {
      case 'idle': return '空闲';
      case 'pending': return '等待执行';
      case 'processing': return '搜索进行中';
      case 'waiting_for_manual': return '等待人工处理';
      case 'pausing': return '暂停中';
      case 'paused': return '已暂停';
      case 'stopping': return '停止中';
      case 'stopped': return '已停止';
      case 'completed': return '搜索完成';
      case 'failed': return '搜索失败';
      default: return progress.status;
    }
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-lg">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2">
            {statusIcon()}
            1688 自动化搜索进度
          </DialogTitle>
          <DialogDescription>
            {progress?.batchId
              ? `批次: ${progress.batchId}${progress.taskId ? ` · 任务: ${progress.taskId.slice(0, 8)}` : ''}`
              : hasVisibleTask
                ? '正在获取进度...'
                : '当前没有可查看的搜索任务'}
          </DialogDescription>
        </DialogHeader>
        <div className="space-y-4 py-2">
          {hasVisibleTask ? (
            <>
              <div className="space-y-2">
                <div className="flex justify-between text-sm">
                  <span className="text-muted-foreground">{statusLabel()}</span>
                  <span className="font-medium">{progress?.processedRows ?? 0} / {progress?.totalRows ?? 0}</span>
                </div>
                <Progress value={percentage} className="h-2" />
                <p className="text-xs text-muted-foreground">{percentage}%</p>
              </div>

              {currentStepLabel && (
                <div className="rounded-md border p-3 text-sm">
                  <p className="text-muted-foreground text-xs mb-1">当前任务</p>
                  <p className="font-medium">{currentStepLabel}</p>
                  {progress.currentRow && (
                    <p className="mt-1 text-xs text-muted-foreground">material_id: {progress.currentRow}</p>
                  )}
                  {currentStage ? (
                    <p className="mt-2 text-xs text-blue-700">
                      {stageTitle(currentStage)} · 已耗时 {formatDurationMs(currentStage.elapsedMs)}
                    </p>
                  ) : null}
                </div>
              )}

              {(stageTiming?.totalElapsedMs != null || completedStages.length > 0) ? (
                <div className="rounded-md border p-3 text-sm">
                  <div className="flex items-center justify-between gap-3">
                    <p className="font-medium">阶段耗时</p>
                    {stageTiming?.totalElapsedMs != null ? (
                      <p className="text-xs text-muted-foreground">总耗时 {formatDurationMs(stageTiming.totalElapsedMs)}</p>
                    ) : null}
                  </div>
                  {completedStages.length > 0 ? (
                    <div className="mt-2 space-y-1">
                      {completedStages.map((stage) => (
                        <div key={`${stage.materialId}-${stage.stageOrder}-${stage.startedAt}`} className="flex justify-between gap-3 text-xs">
                          <span className="truncate text-muted-foreground">{stageTitle(stage)}</span>
                          <span className="shrink-0 font-medium">{formatDurationMs(stage.durationMs ?? stage.elapsedMs)}</span>
                        </div>
                      ))}
                    </div>
                  ) : (
                    <p className="mt-2 text-xs text-muted-foreground">暂无已完成阶段耗时</p>
                  )}
                </div>
              ) : null}

              {isWaitingForManual && (
                <div className="rounded-md border border-orange-200 bg-orange-50 p-3">
                  <p className="text-sm font-medium text-orange-800 mb-1">{manualInterventionTitle(manualIntervention?.kind)}</p>
                  <p className="text-xs text-orange-800/90">{manualIntervention?.message || '请在当前打开的 1688 页面中完成人工验证，脚本会在验证通过后自动继续。'}</p>
                  {manualIntervention?.pageUrl ? (
                    <p className="mt-2 break-all text-[11px] text-orange-700/80">页面：{manualIntervention.pageUrl}</p>
                  ) : null}
                </div>
              )}

              {displayErrors.length > 0 && (
                <div className="rounded-md border border-destructive/30 bg-destructive/5 p-3">
                  <p className="text-sm font-medium text-destructive mb-1">
                    错误 ({displayErrors.length})
                  </p>
                  <div className="max-h-32 overflow-y-auto space-y-1">
                    {displayErrors.map((err, i) => (
                      <p key={i} className="text-xs text-destructive/80">{err}</p>
                    ))}
                  </div>
                </div>
              )}

              {showSummary && progress?.result && (
                <div className="rounded-md border p-3 text-sm space-y-1">
                  <p className="font-medium mb-1">
                    {progress.result.paused
                      ? '搜索已暂停'
                      : progress.result.stopped
                        ? '搜索已停止'
                        : progress.result.success
                          ? '搜索完成'
                          : '搜索失败'}
                  </p>
                  {progress.result.processedRows != null && (
                    <p><span className="text-muted-foreground">已处理：</span>{progress.result.processedRows} / {progress.result.totalRows} 行</p>
                  )}
                  {progress.result.completedRows != null && (
                    <p><span className="text-muted-foreground">完成：</span>{progress.result.completedRows} 行</p>
                  )}
                  {progress.result.failedRows != null && progress.result.failedRows > 0 && (
                    <p><span className="text-muted-foreground">失败：</span><span className="text-destructive">{progress.result.failedRows}</span> 行</p>
                  )}
                  {progress.result.stoppedRows != null && progress.result.stoppedRows > 0 && (
                    <p><span className="text-muted-foreground">停止：</span>{progress.result.stoppedRows} 行</p>
                  )}
                  {progress.result.errorCount != null && progress.result.errorCount > 0 && (
                    <p><span className="text-muted-foreground">错误数：</span><span className="text-destructive">{progress.result.errorCount}</span></p>
                  )}
                  {resultError && !displayErrors.includes(resultError) && (
                    <p className="text-destructive text-xs">{resultError}</p>
                  )}
                  {searchShortage?.message ? (
                    <p className="text-amber-700 text-xs">{searchShortage.message}</p>
                  ) : null}
                  {searchArtifacts ? (
                    <div className="mt-2 space-y-1 border-t pt-2 text-xs text-muted-foreground">
                      <p>LLM JSON：{searchArtifacts.llmMatchResults?.length ?? 0} 个 · 联系方式审计：{searchArtifacts.contactEnrichmentResults?.length ?? 0} 个</p>
                      {searchArtifacts.llmMatchResults?.[0] ? (
                        <p className="break-all">LLM：{searchArtifacts.llmMatchResults[0]}</p>
                      ) : null}
                      {searchArtifacts.llmBatchRecords?.[0] ? (
                        <p className="break-all">Batch：{searchArtifacts.llmBatchRecords[0]}</p>
                      ) : null}
                      {searchArtifacts.llmBatchErrors?.[0] ? (
                        <p className="break-all">Batch错误：{searchArtifacts.llmBatchErrors[0]}</p>
                      ) : null}
                      {searchArtifacts.contactEnrichmentResults?.[0] ? (
                        <p className="break-all">补齐审计：{searchArtifacts.contactEnrichmentResults[0]}</p>
                      ) : null}
                    </div>
                  ) : null}
                </div>
              )}
            </>
          ) : (
            <div className="rounded-md border border-dashed p-4 text-sm text-muted-foreground">
              当前没有可查看的搜索任务。启动新任务后，可以在这里查看进度、暂停、继续或停止当前搜索。
            </div>
          )}
        </div>
        <DialogFooter>
          {canPause && (
            <>
              <Button variant="outline" onClick={handlePause} disabled={action !== null}>
                {action === 'pause' ? <LoaderCircle className="h-4 w-4 animate-spin mr-1.5" /> : <Pause className="h-4 w-4 mr-1.5" />}
                暂停搜索
              </Button>
              <Button variant="destructive" onClick={handleStop} disabled={action !== null}>
                {action === 'stop' ? <LoaderCircle className="h-4 w-4 animate-spin mr-1.5" /> : <Square className="h-4 w-4 mr-1.5" />}
                停止搜索
              </Button>
            </>
          )}
          {isPausing && (
            <>
              <Button variant="outline" disabled>
                <LoaderCircle className="h-4 w-4 animate-spin mr-1.5" />
                暂停中
              </Button>
              <Button variant="destructive" onClick={handleStop} disabled={action !== null}>
                {action === 'stop' ? <LoaderCircle className="h-4 w-4 animate-spin mr-1.5" /> : <Square className="h-4 w-4 mr-1.5" />}
                停止搜索
              </Button>
            </>
          )}
          {isPaused && (
            <>
              <Button onClick={handleResume} disabled={action !== null}>
                {action === 'resume' ? <LoaderCircle className="h-4 w-4 animate-spin mr-1.5" /> : <Play className="h-4 w-4 mr-1.5" />}
                继续搜索
              </Button>
              <Button variant="destructive" onClick={handleStop} disabled={action !== null}>
                {action === 'stop' ? <LoaderCircle className="h-4 w-4 animate-spin mr-1.5" /> : <Square className="h-4 w-4 mr-1.5" />}
                停止搜索
              </Button>
            </>
          )}
          {isStopping && (
            <Button variant="outline" disabled>
              <LoaderCircle className="h-4 w-4 animate-spin mr-1.5" />
              停止中
            </Button>
          )}
          {(!canPause && !isPausing && !isPaused && !isStopping) && (
            <Button onClick={() => onOpenChange(false)}>关闭</Button>
          )}
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
