'use client';

import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';

import { toast } from '@/components/toast/Toast';
import { getSongifyConfig } from '@/config/songify';
import { useApiClient } from '@/lib/apiClient';
import {
  CreateSongifyResponse,
  PresignedUrlRequest,
  PresignedUrlResponse,
  SongifyProject,
  SongifyProjectStatus,
} from '@/types/songify';

import { songifyKeys } from './keys';

export interface CreateProjectOptions {
  name?: string;
  s3FileName: string;
  genre: string;
  numGenerations: number;
  enableLyricOverlay: boolean;
}

export function useSongifyActions() {
  const { t } = useTranslation();
  const apiClient = useApiClient();
  const queryClient = useQueryClient();

  // Get presigned URL for file upload
  const presignedUrlMutation = useMutation({
    mutationFn: async (
      request: PresignedUrlRequest
    ): Promise<PresignedUrlResponse> => {
      const config = getSongifyConfig();

      const params = new URLSearchParams({
        s3_file_name: request.s3_file_name,
        content_type: request.content_type,
        expires_in: String(request.expires_in),
      });

      const controller = new AbortController();
      const timeoutId = setTimeout(() => controller.abort(), 10000);

      try {
        const response = await fetch(
          `${config.presignedUrlEndpoint}?${params.toString()}`,
          { signal: controller.signal }
        );

        clearTimeout(timeoutId);

        if (!response.ok) {
          throw new Error(
            `Failed to get presigned URL: ${response.status} ${response.statusText}`
          );
        }

        const data = await response.json();

        if (!data) {
          throw new Error('No presigned URL received from server');
        }

        return data;
      } catch (error) {
        clearTimeout(timeoutId);
        throw error;
      }
    },
    onError: (error) => {
      console.error('Failed to get presigned URL:', error);
      toast({
        title: t('songify.uploadError', 'Failed to setup file upload'),
        status: 'error',
        duration: 5000,
        isClosable: true,
      });
    },
  });

  // Create a new Songify project
  const createProjectMutation = useMutation({
    mutationFn: async (
      options: CreateProjectOptions
    ): Promise<{ project: SongifyProject; requestId?: string }> => {
      const { name, s3FileName, genre, numGenerations, enableLyricOverlay } =
        options;

      // Create project object with temporary unique ID
      const tempId = `temp_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
      const project: SongifyProject = {
        name: name || `${genre} Project`,
        videos: [],
        createdAt: new Date().toISOString(),
        s3FileName,
        genre,
        numGenerations,
        status: SongifyProjectStatus.PENDING,
        requestId: tempId, // temporary unique ID, will be replaced by backend on success
      };

      try {
        const requestBody = {
          genre: genre,
          original_video_s3_id: s3FileName,
          enable_lyric_overlay: enableLyricOverlay,
          title: name || `${genre} Project`,
        };

        const { data, error, response } = await apiClient.POST(
          '/api/songify/create',
          {
            body: requestBody,
          }
        );

        if (error || !data) {
          const errorMessage = error ? JSON.stringify(error) : 'Unknown error';
          throw new Error(
            `Failed to create project: ${response} ${errorMessage}`
          );
        }

        const responseData = data as CreateSongifyResponse;
        const requestId = responseData.request_id;
        const videos = responseData.video_ids.map((videoId: string) => ({
          id: videoId,
          url: `https://cdn1.suno.ai/songify_video_${videoId}.mp4`,
          status: 'loading' as const,
          genre: genre,
        }));

        project.requestId = requestId;
        project.videos = videos;

        return {
          project: project,
          requestId,
        };
      } catch (error) {
        console.error('Error generating video:', error);
        return { project };
      }
    },
    onSuccess: (result) => {
      // Optimistically add the new project to cache
      if (
        result.project &&
        result.requestId &&
        !result.requestId.startsWith('temp_')
      ) {
        const currentProjects =
          queryClient.getQueryData<SongifyProject[]>(songifyKeys.projects()) ||
          [];

        queryClient.setQueryData(songifyKeys.projects(), [
          ...currentProjects,
          result.project,
        ]);
      }
      // Don't invalidate immediately to avoid race condition with backend persistence
      // The project will be refetched naturally through status polling or user actions

      if (result.requestId && !result.requestId.startsWith('temp_')) {
        toast({
          title: t('songify.projectCreated', 'Project created successfully'),
          description: t(
            'songify.generationStarted',
            'Video generation has started'
          ),
          status: 'info',
          duration: 3000,
          isClosable: true,
        });
      } else {
        toast({
          title: t('songify.projectCreatedWithWarning', 'Project created'),
          description: t(
            'songify.generationMayFail',
            'Generation request failed, but videos may still generate. Check back later.'
          ),
          status: 'warning',
          duration: 5000,
          isClosable: true,
        });
      }
    },
    onError: (error) => {
      console.error('Failed to create project:', error);
      toast({
        title: t('songify.createError', 'Failed to create project'),
        status: 'error',
        duration: 5000,
        isClosable: true,
      });
    },
  });

  // Regenerate project (create a copy with incremented name)
  const regenerateProjectMutation = useMutation({
    mutationFn: async ({
      originalProject,
      newName,
    }: {
      originalProject: SongifyProject;
      newName: string;
    }): Promise<{ project: SongifyProject; requestId?: string }> => {
      const options: CreateProjectOptions = {
        name: newName,
        s3FileName: originalProject.s3FileName,
        genre: originalProject.genre,
        numGenerations: originalProject.numGenerations,
        enableLyricOverlay: false,
      };

      return createProjectMutation.mutateAsync(options);
    },
    onSuccess: () => {
      toast({
        title: t(
          'songify.projectRegenerated',
          'Project regenerated successfully'
        ),
        status: 'info',
        duration: 3000,
        isClosable: true,
      });
    },
    onError: (error) => {
      console.error('Failed to regenerate project:', error);
      toast({
        title: t('songify.regenerateError', 'Failed to regenerate project'),
        status: 'error',
        duration: 5000,
        isClosable: true,
      });
    },
  });

  // Update project metadata (not implemented in backend for metadata changes)
  const updateProjectMutation = useMutation({
    mutationFn: async ({
      requestId,
      updates,
    }: {
      requestId: string;
      updates: Partial<Pick<SongifyProject, 'name' | 'genre'>>;
    }) => {
      const { error, response } = await apiClient.PATCH(
        '/api/songify/{request_id}/update',
        {
          params: {
            path: {
              request_id: requestId,
            },
          },
          body: {
            // Transform frontend 'name' to backend 'title'
            title: updates.name,
            genre: updates.genre,
          },
        }
      );
      if (error || !response) {
        throw new Error('Failed to update project');
      }
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: songifyKeys.projects() });
      toast({
        title: t('songify.projectUpdated', 'Project updated successfully'),
        status: 'info',
        duration: 2000,
        isClosable: true,
      });
    },
  });

  // Delete project (deletes all videos with the same request_id)
  const deleteProjectMutation = useMutation({
    mutationFn: async (requestId: string) => {
      const { error } = await apiClient.DELETE(
        '/api/songify/{request_id}/delete',
        {
          params: {
            path: {
              request_id: requestId,
            },
          },
        }
      );
      if (error) {
        throw new Error('Failed to delete project');
      }
    },
    onSuccess: (_data, requestId) => {
      // Remove specific project query
      queryClient.removeQueries({ queryKey: songifyKeys.project(requestId) });

      // Optimistically remove from projects list
      const currentProjects =
        queryClient.getQueryData<SongifyProject[]>(songifyKeys.projects()) ||
        [];
      queryClient.setQueryData(
        songifyKeys.projects(),
        currentProjects.filter((p) => p.requestId !== requestId)
      );
      toast({
        title: t('songify.projectDeleted', 'Project deleted successfully'),
        status: 'info',
        duration: 2000,
        isClosable: true,
      });
    },
    onError: (error) => {
      console.error('Failed to delete project:', error);
      toast({
        title: t('songify.deleteError', 'Failed to delete project'),
        status: 'error',
        duration: 3000,
        isClosable: true,
      });
    },
  });

  // Delete all projects
  const deleteAllProjectsMutation = useMutation({
    mutationFn: async () => {
      const { error } = await apiClient.DELETE(
        '/api/songify/delete-videos-by-user'
      );
      if (error) {
        throw new Error('Failed to delete all projects');
      }
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: songifyKeys.projects() });
      toast({
        title: t('songify.allProjectsDeleted', 'All projects deleted'),
        status: 'info',
        duration: 2000,
        isClosable: true,
      });
    },
    onError: (error) => {
      console.error('Failed to delete all projects:', error);
      toast({
        title: t('songify.deleteAllError', 'Failed to delete all projects'),
        status: 'error',
        duration: 3000,
        isClosable: true,
      });
    },
  });

  return {
    createProject: createProjectMutation,
    regenerateProject: regenerateProjectMutation,
    updateProject: updateProjectMutation,
    deleteProject: deleteProjectMutation,
    deleteAllProjects: deleteAllProjectsMutation,
    getPresignedUrl: presignedUrlMutation,

    // Loading states
    isCreating: createProjectMutation.isPending,
    isRegenerating: regenerateProjectMutation.isPending,
    isUpdating: updateProjectMutation.isPending,
    isDeleting: deleteProjectMutation.isPending,
    isGettingUploadUrl: presignedUrlMutation.isPending,
  };
}
