import { useCallback, useEffect, useRef, useState } from "react";
import api from "@/shared/api/axios";
import { ApiResponse, unwrap } from "@/shared/api/types";
import { toast } from "sonner";

export interface GeneratedAudio {
  id: string;
  name: string;
  path: string;
  duration_sec: number;
  text: string;
  tts_mode: string;
  language: string;
  created_at: number;
}

interface AudioTask {
  status: string;
  progress?: number;
  message?: string;
  output?: GeneratedAudio & { audio_id: string };
}

interface UseGeneratedAudiosOptions {
  selectedAudioId: string | null;
  setSelectedAudioId: React.Dispatch<React.SetStateAction<string | null>>;
}

export const useGeneratedAudios = ({
  selectedAudioId,
  setSelectedAudioId,
}: UseGeneratedAudiosOptions) => {
  const [generatedAudios, setGeneratedAudios] = useState<GeneratedAudio[]>([]);
  const [selectedAudio, setSelectedAudio] = useState<GeneratedAudio | null>(null);
  const [isGeneratingAudio, setIsGeneratingAudio] = useState(false);
  const [audioTaskId, setAudioTaskId] = useState<string | null>(null);
  const [audioTask, setAudioTask] = useState<AudioTask | null>(null);
  const pollRef = useRef<NodeJS.Timeout | null>(null);

  const fetchGeneratedAudios = useCallback(async (selectId?: string) => {
    try {
      const { data: res } = await api.get<ApiResponse<{ items: GeneratedAudio[] }>>(
        "/api/generated-audios"
      );
      const payload = unwrap(res);
      const items: GeneratedAudio[] = payload.items || [];
      setGeneratedAudios(items);

      if (selectId && items.length > 0) {
        if (selectId === "__latest__") {
          setSelectedAudioId(items[0].id);
          setSelectedAudio(items[0]);
        } else {
          const found = items.find((a) => a.id === selectId);
          if (found) {
            setSelectedAudioId(found.id);
            setSelectedAudio(found);
          }
        }
      }
    } catch (error) {
      console.error("获取配音列表失败:", error);
    }
  }, [setSelectedAudioId]);

  // Sync selectedAudio when selectedAudioId changes externally (e.g. from persistence)
  useEffect(() => {
    if (!selectedAudioId || generatedAudios.length === 0) return;
    const found = generatedAudios.find((a) => a.id === selectedAudioId);
    if (found) {
      setSelectedAudio(found);
    }
  }, [selectedAudioId, generatedAudios]);

  const stopPolling = useCallback(() => {
    if (pollRef.current) {
      clearInterval(pollRef.current);
      pollRef.current = null;
    }
  }, []);

  const startPolling = useCallback((taskId: string) => {
    stopPolling();
    pollRef.current = setInterval(async () => {
      try {
        const { data: res } = await api.get<ApiResponse<AudioTask>>(
          `/api/generated-audios/tasks/${taskId}`
        );
        const task = unwrap(res);
        setAudioTask(task);

        if (task.status === "completed") {
          stopPolling();
          setIsGeneratingAudio(false);
          setAudioTaskId(null);
          // Refresh list and select the new audio
          await fetchGeneratedAudios("__latest__");
          toast.success(task.message || "配音生成完成");
        } else if (task.status === "failed") {
          stopPolling();
          setIsGeneratingAudio(false);
          setAudioTaskId(null);
          toast.error(task.message || "配音生成失败");
        } else if (task.status === "not_found") {
          stopPolling();
          setIsGeneratingAudio(false);
          setAudioTaskId(null);
          setAudioTask(null);
          toast.error("任务已丢失（服务可能已重启），请重新生成");
        }
      } catch {
        // Network error, keep polling
      }
    }, 1000);
  }, [stopPolling, fetchGeneratedAudios]);

  // Cleanup on unmount
  useEffect(() => {
    return () => stopPolling();
  }, [stopPolling]);

  const generateAudio = useCallback(async (params: {
    text: string;
    tts_mode: string;
    voice?: string;
    ref_audio_id?: string;
    ref_text?: string;
    language: string;
    speed?: number;
    instruct_text?: string;
  }) => {
    setIsGeneratingAudio(true);
    setAudioTask({ status: "pending", progress: 0, message: "正在提交..." });

    try {
      const { data: res } = await api.post<ApiResponse<{ task_id: string }>>(
        "/api/generated-audios/generate",
        params
      );
      const { task_id } = unwrap(res);
      setAudioTaskId(task_id);
      startPolling(task_id);
    } catch (err: unknown) {
      setIsGeneratingAudio(false);
      setAudioTask(null);
      const axiosErr = err as { response?: { data?: { message?: string } }; message?: string };
      const errorMsg = axiosErr.response?.data?.message || axiosErr.message || String(err);
      toast.error(`配音生成失败: ${errorMsg}`);
    }
  }, [startPolling]);

  const deleteAudio = useCallback(async (audioId: string) => {
    if (!confirm("确定要删除这个配音吗？")) return;
    try {
      await api.delete(`/api/generated-audios/${encodeURIComponent(audioId)}`);
      if (selectedAudioId === audioId) {
        setSelectedAudioId(null);
        setSelectedAudio(null);
      }
      fetchGeneratedAudios();
    } catch (error) {
      toast.error("删除失败: " + error);
    }
  }, [fetchGeneratedAudios, selectedAudioId, setSelectedAudioId]);

  const renameAudio = useCallback(async (audioId: string, newName: string) => {
    try {
      await api.put(`/api/generated-audios/${encodeURIComponent(audioId)}`, {
        new_name: newName,
      });
      fetchGeneratedAudios();
    } catch (err: unknown) {
      toast.error("重命名失败: " + String(err));
    }
  }, [fetchGeneratedAudios]);

  const selectAudio = useCallback((audio: GeneratedAudio) => {
    setSelectedAudioId(audio.id);
    setSelectedAudio(audio);
  }, [setSelectedAudioId]);

  return {
    generatedAudios,
    selectedAudio,
    selectedAudioId,
    isGeneratingAudio,
    audioTask,
    fetchGeneratedAudios,
    generateAudio,
    deleteAudio,
    renameAudio,
    selectAudio,
  };
};
