import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import type {
  Etape,
  KanbanTask,
  KanbanTaskUpdate,
  TabloFolder,
  TaskStatus,
  UserTablo,
} from "@xtablo/shared-types";
import { clientApi } from "../lib/api";

type ClientTaskCreateInput = {
  tablo_id: string;
  title: string;
  status?: TaskStatus | string;
  parent_task_id?: string | null;
  is_parent?: boolean;
  position?: number;
  description?: string | null;
  assignee_id?: string | null;
  due_date?: string | null;
};

export function useClientTablos() {
  return useQuery<UserTablo[]>({
    queryKey: ["client-portal", "tablos"],
    queryFn: async () => {
      const { data } = await clientApi.get<{ tablos: UserTablo[] }>("/api/v1/client-portal/tablos");
      return data.tablos ?? [];
    },
  });
}

export function useClientTablo(tabloId: string) {
  return useQuery<UserTablo>({
    queryKey: ["client-portal", "tablo", tabloId],
    queryFn: async () => {
      const { data } = await clientApi.get<{ tablo: UserTablo }>(
        `/api/v1/client-portal/tablos/${tabloId}`
      );
      return data.tablo;
    },
    enabled: Boolean(tabloId),
  });
}

export function useClientTabloTasks(tabloId: string) {
  return useQuery<KanbanTask[]>({
    queryKey: ["client-portal", "tasks", tabloId],
    queryFn: async () => {
      const { data } = await clientApi.get<{ tasks: KanbanTask[] }>(
        `/api/v1/client-portal/tablos/${tabloId}/tasks`
      );
      return data.tasks ?? [];
    },
    enabled: Boolean(tabloId),
  });
}

export function useClientTabloEtapes(tabloId: string) {
  return useQuery<Etape[]>({
    queryKey: ["client-portal", "etapes", tabloId],
    queryFn: async () => {
      const { data } = await clientApi.get<{ etapes: Etape[] }>(
        `/api/v1/client-portal/tablos/${tabloId}/etapes`
      );
      return data.etapes ?? [];
    },
    enabled: Boolean(tabloId),
  });
}

export function useClientTabloEvents(tabloId: string) {
  return useQuery({
    queryKey: ["client-portal", "events", tabloId],
    queryFn: async () => {
      const { data } = await clientApi.get<{ events: unknown[] }>(
        `/api/v1/client-portal/tablos/${tabloId}/events`
      );
      return data.events ?? [];
    },
    enabled: Boolean(tabloId),
  });
}

export function useClientTabloMembers(tabloId: string) {
  return useQuery({
    queryKey: ["client-portal", "members", tabloId],
    queryFn: async () => {
      const { data } = await clientApi.get<{
        members: {
          id: string;
          name: string;
          is_admin: boolean;
          email: string;
          avatar_url: string | null;
        }[];
      }>(`/api/v1/client-portal/tablos/${tabloId}/members`);
      return data.members ?? [];
    },
    enabled: Boolean(tabloId),
  });
}

export function useClientTabloFiles(tabloId: string) {
  return useQuery<{ fileNames: string[] }>({
    queryKey: ["client-portal", "files", tabloId],
    queryFn: async () => {
      const { data } = await clientApi.get<{ fileNames: string[] }>(
        `/api/v1/client-portal/tablos/${tabloId}/files`
      );
      return data;
    },
    enabled: Boolean(tabloId),
  });
}

export function useClientTabloFolders(tabloId: string) {
  return useQuery<TabloFolder[]>({
    queryKey: ["client-portal", "folders", tabloId],
    queryFn: async () => {
      const { data } = await clientApi.get<{ folders: TabloFolder[] }>(
        `/api/v1/client-portal/tablos/${tabloId}/folders`
      );
      return data.folders ?? [];
    },
    enabled: Boolean(tabloId),
  });
}

const invalidateClientFileQueries = (queryClient: ReturnType<typeof useQueryClient>, tabloId: string) => {
  queryClient.invalidateQueries({ queryKey: ["client-portal", "files", tabloId] });
  queryClient.invalidateQueries({ queryKey: ["client-portal", "folders", tabloId] });
};

const invalidateClientTaskQueries = (queryClient: ReturnType<typeof useQueryClient>, tabloId: string) => {
  queryClient.invalidateQueries({ queryKey: ["client-portal", "tasks", tabloId] });
  queryClient.invalidateQueries({ queryKey: ["client-portal", "etapes", tabloId] });
};

export function useClientCreateFile(tabloId: string) {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (params: {
      tabloId: string;
      fileName: string;
      data: { content: string; contentType: string };
    }) => {
      const { data } = await clientApi.post(
        `/api/v1/client-portal/tablos/${params.tabloId}/file/${params.fileName}`,
        params.data
      );

      return data;
    },
    onSuccess: () => invalidateClientFileQueries(queryClient, tabloId),
  });
}

export function useClientDownloadFile() {
  return useMutation({
    mutationFn: async ({ tabloId, fileName }: { tabloId: string; fileName: string }) => {
      const response = await clientApi.get<{
        content: string;
        contentType?: string;
      }>(`/api/v1/client-portal/tablos/${tabloId}/file/${fileName}`);

      const fileData = response.data;
      let blob: Blob;

      if (fileData.content.startsWith("data:")) {
        const fileResponse = await fetch(fileData.content);
        blob = await fileResponse.blob();
      } else {
        blob = new Blob([fileData.content], {
          type: fileData.contentType || "application/octet-stream",
        });
      }

      const url = window.URL.createObjectURL(blob);
      const link = document.createElement("a");
      link.href = url;
      link.download = fileName;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.URL.revokeObjectURL(url);
    },
  });
}

export function useClientCreateFolder(tabloId: string) {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (params: {
      tabloId: string;
      name: string;
      description: string;
      createdBy: string;
    }) => {
      const { data } = await clientApi.post(`/api/v1/client-portal/tablos/${params.tabloId}/folders`, {
        description: params.description,
        name: params.name,
      });

      return data;
    },
    onSuccess: () => invalidateClientFileQueries(queryClient, tabloId),
  });
}

export function useClientUpdateFolder(tabloId: string) {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (params: {
      tabloId: string;
      folderId: string;
      name: string;
      description: string;
    }) => {
      const { data } = await clientApi.put(
        `/api/v1/client-portal/tablos/${params.tabloId}/folders/${params.folderId}`,
        {
          description: params.description,
          name: params.name,
        }
      );

      return data;
    },
    onSuccess: () => invalidateClientFileQueries(queryClient, tabloId),
  });
}

export function useClientDeleteFolder(tabloId: string) {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (params: { tabloId: string; folderId: string; folderName: string }) => {
      const { data } = await clientApi.delete(
        `/api/v1/client-portal/tablos/${params.tabloId}/folders/${params.folderId}`
      );

      return data;
    },
    onSuccess: () => invalidateClientFileQueries(queryClient, tabloId),
  });
}

export function useClientCreateTask(tabloId: string) {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (task: ClientTaskCreateInput) => {
      const { data } = await clientApi.post<{ task: unknown }>(
        `/api/v1/client-portal/tablos/${tabloId}/tasks`,
        task
      );

      return data.task;
    },
    onSuccess: () => invalidateClientTaskQueries(queryClient, tabloId),
  });
}

export function useClientUpdateTask(tabloId: string) {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async ({
      id,
      tablo_id: _tabloId,
      ...updates
    }: KanbanTaskUpdate & { id: string; tablo_id?: string }) => {
      const { data } = await clientApi.patch<{ task: unknown }>(
        `/api/v1/client-portal/tablos/${tabloId}/tasks/${id}`,
        updates
      );

      return data.task;
    },
    onSuccess: () => invalidateClientTaskQueries(queryClient, tabloId),
  });
}

export function useClientDeleteTask(tabloId: string) {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (taskId: string) => {
      await clientApi.delete(`/api/v1/client-portal/tablos/${tabloId}/tasks/${taskId}`);
      return taskId;
    },
    onSuccess: () => invalidateClientTaskQueries(queryClient, tabloId),
  });
}

export function useClientUpdateTaskPositions(tabloId: string) {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (
      updates: Array<{
        id: string;
        position: number;
        status?: TaskStatus;
        parent_task_id?: string | null;
      }>
    ) => {
      await Promise.all(
        updates.map(({ id, ...taskUpdates }) =>
          clientApi.patch(`/api/v1/client-portal/tablos/${tabloId}/tasks/${id}`, taskUpdates)
        )
      );

      return updates;
    },
    onSuccess: () => invalidateClientTaskQueries(queryClient, tabloId),
  });
}
