import { useEffect, useRef, useCallback, useState } from 'react';
import { toast } from 'sonner';
import { DefaultService } from '@/lib/api';
import { logger } from '@/lib/utils/logger';

/** 任务状态类型 */
type TaskStatus = 'pending' | 'processing' | 'success' | 'failed' | 'cancelled' | 'timeout' | 'retrying';

/** 轮询任务配置 */
interface PollingTask {
  /** 任务唯一标识 */
  taskId: string;
  /** 任务类型（如：图片生成、视频生成） */
  taskType: string;
  /** 关联的节点 ID（可选） */
  nodeId?: string;
  /** 任务完成回调函数 */
  onComplete?: (result: { status: TaskStatus; urls?: string[]; error?: string }) => void;
  /** 进度更新回调函数 */
  onProgress?: (progress: number) => void;
}

/** 任务状态对象 */
interface TaskState {
  /** 当前任务状态 */
  status: TaskStatus;
  /** 当前进度（0-100） */
  progress: number;
  /** 生成的资源 URL 列表 */
  urls?: string[];
  /** 错误信息（如果任务失败） */
  error?: string;
  /** 已尝试轮询次数 */
  attempts: number;
}

interface UseTaskPollingOptions {
  /** 默认轮询间隔（毫秒） */
  defaultInterval?: number;
  /** 快速轮询阶段次数（使用较短间隔） */
  fastPollAttempts?: number;
  /** 快速轮询间隔 */
  fastPollInterval?: number;
  /** 最大轮询次数 */
  maxAttempts?: number;
  /** 是否启用通知 */
  enableNotifications?: boolean;
}

const log = logger.namespace('useTaskPolling');

/**
 * 任务轮询 Hook - 替代 WebSocket 实时推送
 *
 * 特性：
 * - 支持多任务并发轮询
 * - 动态轮询间隔（前期频繁，后期放缓）
 * - 页面隐藏时暂停，显示时恢复
 * - 自动触发 toast 通知
 * - 任务完成后自动清理
 */
export function useTaskPolling(options: UseTaskPollingOptions = {}) {
  const {
    defaultInterval = 5000,
    fastPollAttempts = 6, // 前 6 次使用快速轮询
    fastPollInterval = 2000,
    maxAttempts = 120,
    enableNotifications = true,
  } = options;

  const [tasks, setTasks] = useState<Map<string, TaskState>>(new Map());
  const pollingTasksRef = useRef<Map<string, PollingTask>>(new Map());
  const abortControllersRef = useRef<Map<string, AbortController>>(new Map());
  const pageVisibleRef = useRef(true);
  const resumePollingRef = useRef<Set<string>>(new Set());

  // 获取任务的轮询间隔
  const getInterval = useCallback(
    (attempts: number) => {
      if (attempts < fastPollAttempts) {
        return fastPollInterval;
      }
      // 渐进式增加间隔，但不超过 10 秒
      return Math.min(defaultInterval + (attempts - fastPollAttempts) * 500, 10000);
    },
    [fastPollAttempts, fastPollInterval, defaultInterval]
  );

  // 发送通知
  const sendNotification = useCallback(
    (taskId: string, taskType: string, status: TaskStatus, error?: string) => {
      if (!enableNotifications) return;

      const shortId = taskId.slice(0, 8);

      switch (status) {
        case 'success':
          toast.success(`${taskType} 生成完成`, {
            description: `任务 #${shortId} 已完成`,
            duration: 5000,
          });
          break;
        case 'failed':
          toast.error(`${taskType} 生成失败`, {
            description: error || `任务 #${shortId} 执行失败`,
            duration: 5000,
          });
          break;
        case 'cancelled':
          toast.info(`${taskType} 已取消`, {
            description: `任务 #${shortId} 已取消`,
            duration: 3000,
          });
          break;
        case 'timeout':
          toast.error(`${taskType} 生成超时`, {
            description: `任务 #${shortId} 执行超时`,
            duration: 5000,
          });
          break;
      }
    },
    [enableNotifications]
  );

  // 执行单次轮询
  const pollOnce = useCallback(
    async (taskId: string): Promise<{ shouldContinue: boolean; state?: TaskState }> => {
      const task = pollingTasksRef.current.get(taskId);
      if (!task) return { shouldContinue: false };

      const currentState = tasks.get(taskId) || {
        status: 'pending' as TaskStatus,
        progress: 0,
        attempts: 0,
      };

      if (currentState.attempts >= maxAttempts) {
        const timeoutState: TaskState = {
          ...currentState,
          status: 'timeout',
          error: '轮询超时',
        };
        sendNotification(taskId, task.taskType, 'timeout');
        task.onComplete?.({ status: 'timeout', error: '轮询超时' });
        return { shouldContinue: false, state: timeoutState };
      }

      try {
        const response = await DefaultService.getTaskStatus(taskId);
        // BaseResponse structure: { code, message, data: { status, result, ... } }
        const taskData = (response as any).data?.data;

        if (!taskData) {
          throw new Error('No data returned');
        }

        const rawStatus = String(taskData.status || '').toLowerCase();
        let status: TaskStatus;
        let progress = currentState.progress;
        let urls: string[] | undefined;
        let error: string | undefined;

        // 状态映射
        if (rawStatus === 'succeeded' || rawStatus === 'success') {
          status = 'success';
          urls = taskData.result?.urls || [];
        } else if (rawStatus === 'failed') {
          status = 'failed';
          error = taskData.error || '任务失败';
        } else if (rawStatus === 'cancelled' || rawStatus === 'canceled') {
          status = 'cancelled';
        } else if (rawStatus === 'retrying') {
          status = 'retrying';
        } else {
          status = 'processing';
          // 模拟进度（可以根据实际需要调整）
          progress = Math.min(
            10 + currentState.attempts * 2,
            95
          );
        }

        const newState: TaskState = {
          status,
          progress,
          urls,
          error,
          attempts: currentState.attempts + 1,
        };

        // 任务完成
        if (['success', 'failed', 'cancelled'].includes(status)) {
          sendNotification(taskId, task.taskType, status, error);
          task.onComplete?.({ status, urls, error });
          return { shouldContinue: false, state: newState };
        }

        // 继续轮询
        task.onProgress?.(progress);
        return { shouldContinue: true, state: newState };
      } catch (err) {
        log.error(`Polling error for task ${taskId}:`, err);
        // 网络错误继续轮询，但增加尝试次数
        const newState: TaskState = {
          ...currentState,
          attempts: currentState.attempts + 1,
        };
        return { shouldContinue: true, state: newState };
      }
    },
    [maxAttempts, sendNotification, tasks]
  );

  // 轮询循环
  const pollLoop = useCallback(
    async (taskId: string) => {
      while (true) {
        // 页面不可见时暂停
        if (!pageVisibleRef.current) {
          resumePollingRef.current.add(taskId);
          log.debug(`Polling paused for ${taskId} (page hidden)`);
          return;
        }

        const { shouldContinue, state } = await pollOnce(taskId);

        if (state) {
          setTasks((prev) => {
            const next = new Map(prev);
            next.set(taskId, state);
            return next;
          });
        }

        if (!shouldContinue) {
          // 轮询结束，清理
          pollingTasksRef.current.delete(taskId);
          abortControllersRef.current.delete(taskId);
          resumePollingRef.current.delete(taskId);
          return;
        }

        // 等待下次轮询
        const interval = getInterval(state?.attempts || 0);
        await new Promise((resolve) => setTimeout(resolve, interval));
      }
    },
    [pollOnce, getInterval]
  );

  // 开始轮询任务
  const startPolling = useCallback(
    (params: PollingTask) => {
      const { taskId } = params;

      // 已在轮询中则忽略
      if (pollingTasksRef.current.has(taskId)) {
        log.debug(`Task ${taskId} already being polled`);
        return;
      }

      log.debug(`Starting polling for task ${taskId}`);
      pollingTasksRef.current.set(taskId, params);

      // 初始化任务状态
      setTasks((prev) => {
        const next = new Map(prev);
        next.set(taskId, {
          status: 'pending',
          progress: 0,
          attempts: 0,
        });
        return next;
      });

      // 启动轮询
      pollLoop(taskId);
    },
    [pollLoop]
  );

  // 停止轮询任务
  const stopPolling = useCallback((taskId: string) => {
    log.debug(`Stopping polling for task ${taskId}`);
    pollingTasksRef.current.delete(taskId);
    abortControllersRef.current.get(taskId)?.abort();
    abortControllersRef.current.delete(taskId);
    resumePollingRef.current.delete(taskId);
    setTasks((prev) => {
      const next = new Map(prev);
      next.delete(taskId);
      return next;
    });
  }, []);

  // 获取任务状态
  const getTaskState = useCallback(
    (taskId: string): TaskState | undefined => {
      return tasks.get(taskId);
    },
    [tasks]
  );

  // 页面可见性变化处理
  useEffect(() => {
    const handleVisibilityChange = () => {
      const isVisible = !document.hidden;
      pageVisibleRef.current = isVisible;

      if (isVisible) {
        // 页面显示时，恢复之前暂停的轮询
        resumePollingRef.current.forEach((taskId) => {
          log.debug(`Resuming polling for ${taskId}`);
          pollLoop(taskId);
        });
        resumePollingRef.current.clear();
      }
    };

    document.addEventListener('visibilitychange', handleVisibilityChange);
    return () => {
      document.removeEventListener('visibilitychange', handleVisibilityChange);
    };
  }, [pollLoop]);

  // 清理所有轮询
  const stopAll = useCallback(() => {
    pollingTasksRef.current.clear();
    abortControllersRef.current.forEach((controller) => controller.abort());
    abortControllersRef.current.clear();
    resumePollingRef.current.clear();
    setTasks(new Map());
  }, []);

  // 组件卸载时清理
  useEffect(() => {
    return () => {
      stopAll();
    };
  }, [stopAll]);

  return {
    tasks,
    startPolling,
    stopPolling,
    stopAll,
    getTaskState,
  };
}

export type { PollingTask, TaskState, TaskStatus, UseTaskPollingOptions };
