/**
 * React Query hooks for layout management
 */

import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import type { UseQueryResult, UseMutationResult } from "@tanstack/react-query";
import type { UserLayout, WidgetPlacement } from "@mosaic/shared";

const LAYOUTS_KEY = ["layouts"];

interface CreateLayoutData {
  name: string;
  layout: WidgetPlacement[];
  isDefault?: boolean;
  metadata?: Record<string, unknown>;
}

interface UpdateLayoutData {
  id: string;
  name?: string;
  layout?: WidgetPlacement[];
  isDefault?: boolean;
  metadata?: Record<string, unknown>;
}

/**
 * Fetch all layouts for the current user
 */
export function useLayouts(): UseQueryResult<UserLayout[]> {
  return useQuery<UserLayout[]>({
    queryKey: LAYOUTS_KEY,
    queryFn: async (): Promise<UserLayout[]> => {
      const response = await fetch("/api/layouts");
      if (!response.ok) {
        throw new Error("Failed to fetch layouts");
      }
      return response.json() as Promise<UserLayout[]>;
    },
  });
}

/**
 * Fetch a single layout by ID
 */
export function useLayout(id: string): UseQueryResult<UserLayout> {
  return useQuery<UserLayout>({
    queryKey: [...LAYOUTS_KEY, id],
    queryFn: async (): Promise<UserLayout> => {
      const response = await fetch(`/api/layouts/${id}`);
      if (!response.ok) {
        throw new Error("Failed to fetch layout");
      }
      return response.json() as Promise<UserLayout>;
    },
    enabled: !!id,
  });
}

/**
 * Fetch the default layout
 */
export function useDefaultLayout(): UseQueryResult<UserLayout> {
  return useQuery<UserLayout>({
    queryKey: [...LAYOUTS_KEY, "default"],
    queryFn: async (): Promise<UserLayout> => {
      const response = await fetch("/api/layouts/default");
      if (!response.ok) {
        throw new Error("Failed to fetch default layout");
      }
      return response.json() as Promise<UserLayout>;
    },
  });
}

/**
 * Create a new layout
 */
export function useCreateLayout(): UseMutationResult<UserLayout, Error, CreateLayoutData> {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (data: CreateLayoutData): Promise<UserLayout> => {
      const response = await fetch("/api/layouts", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(data),
      });

      if (!response.ok) {
        throw new Error("Failed to create layout");
      }

      return response.json() as Promise<UserLayout>;
    },
    onSuccess: (): void => {
      // Invalidate layouts cache to refetch
      void queryClient.invalidateQueries({ queryKey: LAYOUTS_KEY });
    },
  });
}

/**
 * Update an existing layout
 */
export function useUpdateLayout(): UseMutationResult<UserLayout, Error, UpdateLayoutData> {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async ({ id, ...data }: UpdateLayoutData): Promise<UserLayout> => {
      const response = await fetch(`/api/layouts/${id}`, {
        method: "PATCH",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(data),
      });

      if (!response.ok) {
        throw new Error("Failed to update layout");
      }

      return response.json() as Promise<UserLayout>;
    },
    onSuccess: (_data, variables): void => {
      // Invalidate affected queries
      void queryClient.invalidateQueries({ queryKey: LAYOUTS_KEY });
      void queryClient.invalidateQueries({ queryKey: [...LAYOUTS_KEY, variables.id] });
    },
  });
}

/**
 * Delete a layout
 */
export function useDeleteLayout(): UseMutationResult<void, Error, string> {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (id: string): Promise<void> => {
      const response = await fetch(`/api/layouts/${id}`, {
        method: "DELETE",
      });

      if (!response.ok) {
        throw new Error("Failed to delete layout");
      }

      await response.json();
    },
    onSuccess: (): void => {
      // Invalidate layouts cache to refetch
      void queryClient.invalidateQueries({ queryKey: LAYOUTS_KEY });
    },
  });
}

interface UseSaveLayoutReturn {
  saveLayout: (layout: WidgetPlacement[]) => void;
  isSaving: boolean;
  error: Error | null;
}

/**
 * Helper hook to save layout changes with debouncing
 */
export function useSaveLayout(layoutId: string): UseSaveLayoutReturn {
  const updateLayout = useUpdateLayout();

  const saveLayout = (layout: WidgetPlacement[]): void => {
    updateLayout.mutate({
      id: layoutId,
      layout,
    });
  };

  return {
    saveLayout,
    isSaving: updateLayout.isPending,
    error: updateLayout.error,
  };
}
