import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { aiApi } from "../lib/api/ai";
import type { Character, Episode, Outline, Scene, Storyboard, StructuredVideoRequest } from "../lib/api/ai";

// ---- Characters ----
const charactersKey = (pid: string) => ["characters", pid];

export function useCharacters(projectId: string) {
  return useQuery({ queryKey: charactersKey(projectId), queryFn: () => aiApi.listCharacters(projectId), enabled: !!projectId });
}
export function useExtractCharacters(projectId: string) {
  const qc = useQueryClient();
  return useMutation({ mutationFn: () => aiApi.extractCharacters(projectId), onSuccess: () => qc.invalidateQueries({ queryKey: charactersKey(projectId) }) });
}
export function useSaveCharacter(projectId: string) {
  const qc = useQueryClient();
  return useMutation({ mutationFn: (req: Partial<Character>) => aiApi.saveCharacter(projectId, req), onSuccess: () => qc.invalidateQueries({ queryKey: charactersKey(projectId) }) });
}
export function useGenerateCharacterImage(projectId: string) {
  const qc = useQueryClient();
  return useMutation({ mutationFn: (id: string) => aiApi.generateCharacterImage(projectId, id), onSuccess: () => qc.invalidateQueries({ queryKey: charactersKey(projectId) }) });
}
export function useUploadCharacterImage(projectId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: ({ id, file, viewType }: { id: string; file: File; viewType: "front" | "side" | "back" }) =>
      aiApi.uploadCharacterImage(projectId, id, file, viewType),
    onSuccess: () => qc.invalidateQueries({ queryKey: charactersKey(projectId) }),
  });
}
export function useDeleteCharacter(projectId: string) {
  const qc = useQueryClient();
  return useMutation({ mutationFn: (id: string) => aiApi.deleteCharacter(projectId, id), onSuccess: () => qc.invalidateQueries({ queryKey: charactersKey(projectId) }) });
}

// ---- Scenes ----
const scenesKey = (pid: string) => ["scenes", pid];

export function useScenes(projectId: string) {
  return useQuery({ queryKey: scenesKey(projectId), queryFn: () => aiApi.listScenes(projectId), enabled: !!projectId });
}
export function useExtractScenes(projectId: string) {
  const qc = useQueryClient();
  return useMutation({ mutationFn: () => aiApi.extractScenes(projectId), onSuccess: () => qc.invalidateQueries({ queryKey: scenesKey(projectId) }) });
}
export function useSaveScene(projectId: string) {
  const qc = useQueryClient();
  return useMutation({ mutationFn: (req: Partial<Scene>) => aiApi.saveScene(projectId, req), onSuccess: () => qc.invalidateQueries({ queryKey: scenesKey(projectId) }) });
}
export function useGenerateSceneImage(projectId: string) {
  const qc = useQueryClient();
  return useMutation({ mutationFn: (id: string) => aiApi.generateSceneImage(projectId, id), onSuccess: () => qc.invalidateQueries({ queryKey: scenesKey(projectId) }) });
}
export function useUploadSceneImage(projectId: string) {
  const qc = useQueryClient();
  return useMutation({ mutationFn: ({ id, file }: { id: string; file: File }) => aiApi.uploadSceneImage(projectId, id, file), onSuccess: () => qc.invalidateQueries({ queryKey: scenesKey(projectId) }) });
}
export function useDeleteScene(projectId: string) {
  const qc = useQueryClient();
  return useMutation({ mutationFn: (id: string) => aiApi.deleteScene(projectId, id), onSuccess: () => qc.invalidateQueries({ queryKey: scenesKey(projectId) }) });
}

const outlineKey = (pid: string) => ["outline", pid];
const episodesKey = (pid: string) => ["episodes", pid];
const storyboardsKey = (pid: string, eid: string) => ["storyboards", pid, eid];
const videoTasksKey = (pid: string) => ["video-tasks", pid];
const assemblyKey = (pid: string, eid: string) => ["assembly", pid, eid];

// ---- Outline ----
export function useOutline(projectId: string) {
  return useQuery({
    queryKey: outlineKey(projectId),
    queryFn: () => aiApi.getOutline(projectId),
    enabled: !!projectId,
    retry: false,
  });
}

export function useGenerateOutline(projectId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (script: string) => aiApi.generateOutline(projectId, script),
    onSuccess: () => qc.invalidateQueries({ queryKey: outlineKey(projectId) }),
  });
}

export function useUpdateOutline(projectId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (patch: Partial<Outline>) => aiApi.updateOutline(projectId, patch),
    onSuccess: () => qc.invalidateQueries({ queryKey: outlineKey(projectId) }),
  });
}

// ---- Episodes ----
export function useEpisodes(projectId: string) {
  return useQuery({
    queryKey: episodesKey(projectId),
    queryFn: () => aiApi.listEpisodes(projectId),
    enabled: !!projectId,
    staleTime: 0,
  });
}

export function useGenerateEpisodes(projectId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: () => aiApi.generateEpisodes(projectId),
    onSuccess: () => qc.invalidateQueries({ queryKey: episodesKey(projectId) }),
  });
}

export function useCreateEpisode(projectId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (req: Partial<Episode>) => aiApi.createEpisode(projectId, req),
    onSuccess: () => qc.invalidateQueries({ queryKey: episodesKey(projectId) }),
  });
}

export function useUpdateEpisode(projectId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: ({ id, patch }: { id: string; patch: Partial<Episode> }) =>
      aiApi.updateEpisode(projectId, id, patch),
    onSuccess: () => qc.invalidateQueries({ queryKey: episodesKey(projectId) }),
  });
}

// ---- Storyboards ----
export function useStoryboards(projectId: string, episodeId: string) {
  return useQuery({
    queryKey: storyboardsKey(projectId, episodeId),
    queryFn: () => aiApi.listStoryboards(projectId, episodeId),
    enabled: !!projectId && !!episodeId,
  });
}

export function useCreateStoryboard(projectId: string, episodeId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (req: Partial<Storyboard> | Record<string, unknown>) =>
      aiApi.createStoryboard(projectId, episodeId, req as Storyboard),
    onSuccess: () => qc.invalidateQueries({ queryKey: storyboardsKey(projectId, episodeId) }),
  });
}

export function useGenerateStoryboards(projectId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (episodeId: string) => aiApi.generateStoryboards(projectId, episodeId),
    onSuccess: (_, episodeId) => qc.invalidateQueries({ queryKey: storyboardsKey(projectId, episodeId) }),
  });
}

export function useUpdateStoryboard(projectId: string, episodeId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: ({ id, patch }: { id: string; patch: Record<string, unknown> }) =>
      aiApi.updateStoryboard(projectId, id, patch),
    onSuccess: () => qc.invalidateQueries({ queryKey: storyboardsKey(projectId, episodeId) }),
  });
}

export function useDeleteStoryboard(projectId: string, episodeId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (id: string) => aiApi.deleteStoryboard(projectId, id),
    onSuccess: () => qc.invalidateQueries({ queryKey: storyboardsKey(projectId, episodeId) }),
  });
}

export function useReorderStoryboards(projectId: string, episodeId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (ids: string[]) => aiApi.reorderStoryboards(projectId, ids),
    onSuccess: () => qc.invalidateQueries({ queryKey: storyboardsKey(projectId, episodeId) }),
  });
}

export function useGenerateStoryboardPrompt(projectId: string) {
  return useMutation({
    mutationFn: (storyboardId: string) => aiApi.generateStoryboardPrompt(projectId, storyboardId),
  });
}

// ---- Video Tasks ----
export function useVideoTasks(projectId: string) {
  return useQuery({
    queryKey: videoTasksKey(projectId),
    queryFn: () => aiApi.listVideoTasks(projectId),
    enabled: !!projectId,
    staleTime: 0,
    refetchOnWindowFocus: true,
    refetchInterval: (query) => {
      const tasks = query.state.data;
      if (!tasks) return false;
      const hasActive = tasks.some(
        (t) => t.status === "pending" || t.status === "submitted" || t.status === "running"
      );
      return hasActive ? 5000 : false;
    },
  });
}

export function useGenerateVideo(projectId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: ({ episodeId, prompt, videoPrompt, storyboardId, imageKeys, duration }: {
      episodeId: string | null;
      prompt: string;
      videoPrompt?: string;
      storyboardId?: string | null;
      imageKeys?: string[] | null;
      duration?: number;
    }) => aiApi.generateVideo(projectId, episodeId, prompt, videoPrompt, storyboardId, imageKeys, duration),
    onSuccess: () => qc.invalidateQueries({ queryKey: videoTasksKey(projectId) }),
  });
}

export function useGenerateStructuredVideo(projectId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (req: StructuredVideoRequest) => aiApi.generateStructuredVideo(projectId, req),
    onSuccess: () => qc.invalidateQueries({ queryKey: videoTasksKey(projectId) }),
  });
}

// ---- Assembly ----
export function useAssemblyTask(projectId: string, episodeId: string) {
  return useQuery({
    queryKey: assemblyKey(projectId, episodeId),
    queryFn: () => aiApi.getAssemblyTask(projectId, episodeId),
    enabled: !!projectId && !!episodeId,
    refetchInterval: (query) => {
      const data = query.state.data;
      if (!data) return false;
      const { status } = data;
      return status === "succeeded" || status === "failed" ? false : 5000;
    },
  });
}

export function useStartAssembly(projectId: string, episodeId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: () => aiApi.startAssembly(projectId, episodeId),
    onSuccess: () => qc.invalidateQueries({ queryKey: assemblyKey(projectId, episodeId) }),
  });
}

export function useDeleteVideoTask(projectId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (taskId: string) => aiApi.deleteVideoTask(projectId, taskId),
    onSuccess: () => qc.invalidateQueries({ queryKey: videoTasksKey(projectId) }),
  });
}

export function usePollVideoTask(projectId: string, taskId: string, enabled: boolean) {
  return useQuery({
    queryKey: ["video-task", projectId, taskId],
    queryFn: () => aiApi.pollVideoTask(projectId, taskId),
    enabled: enabled && !!taskId,
    refetchInterval: (query) => {
      const status = query.state.data?.status;
      return status === "succeeded" || status === "failed" ? false : 5000;
    },
  });
}
