import {
  ICollaborator,
  ITaskItem,
  IUnderTask,
  collaborator,
} from "@/contexts/types/tasks";
import axios, {
  axiosInstance1,
  endpoints,
  fetcher1,
  fetcher2,
} from "@/utils/axios";
import { useMemo } from "react";
import useSWR, { mutate } from "swr";

const URL = endpoints.task.add;
export async function createTask(taskData: ITaskItem) {
  return await axios.post(URL, taskData);
}

export function useGetTasks(agencyId: number, state: string) {
  const URL = endpoints.task.list(agencyId, state);

  const { data, isLoading, error, isValidating } = useSWR(URL, fetcher1);

  const memoizedValue = useMemo(
    () => ({
      tasks: data || [],
      tasksLoading: isLoading,
      tasksError: error,
      tasksValidating: isValidating,
      tasksEmpty: !isLoading && !data?.length,
    }),
    [data, error, isLoading, isValidating]
  );

  return memoizedValue;
}

export function useGetTask(taskId: number) {
  const URL = `${endpoints.task.get}/${taskId}`;
  const { data, isLoading, error } = useSWR<ITaskItem>(URL, fetcher1);
  return {
    taskData: data as ITaskItem,
    taskIsLoading: isLoading,
    taskError: error,
  };
}
//-------------------------ARCHIVE & RECOVER---------------------------
export async function archiveTask(taskId: number) {
  try {
    const response = await axiosInstance1.post(
      `${endpoints.task.archive}/${taskId}`
    );
    const Data = await response.data;
    mutate([endpoints.task.list]);
    return Data;
  } catch (error) {
    console.error("Error archiving task:", error);
    throw error;
  }
}

export async function archiveListTask(taskIds: number[]) {
  try {
    const archivePromises = taskIds.map(async (taskId) => {
      await archiveTask(taskId);
    });

    await Promise.all(archivePromises);

    mutate(endpoints.task.list);
    return archivePromises;
  } catch (error) {
    console.error("Error archiving tasks:", error);
    throw error;
  }
}

export async function recoverTask(taskId: number) {
  try {
    const response = await axiosInstance1.put(
      `${endpoints.task.recover}/${taskId}`
    );
    const newData = await response.data;
    mutate(endpoints.task.list);
    return newData;
  } catch (error) {
    console.error("Recorve task error:", error);
    throw error;
  }
}

export async function recoverListTask(taskIds: number[]) {
  try {
    const recoverPromises = taskIds.map(async (taskId) => {
      await recoverTask(taskId);
    });
    await Promise.all(recoverPromises);
    mutate(endpoints.task.list);
    return recoverPromises;
  } catch (error) {
    console.error("Recorve tasks error", error);
    throw error;
  }
}

//---------------------delete-----------------
export async function deleteTask(taskId: number) {
  try {
    const response = await axiosInstance1.delete(
      `${endpoints.task.delete}/${taskId}`
    );
    const newData = await response.data;
    mutate(endpoints.task.list);
    return newData;
  } catch (error) {
    console.error(" delete task Error:", error);
    throw error;
  }
}
export async function deleteListTask(taskIds: number[]) {
  try {
    const deletePromises = taskIds.map(async (taskId) => {
      await deleteTask(taskId);
    });

    await Promise.all(deletePromises);

    mutate(endpoints.task.list);

    return deletePromises;
  } catch (error) {
    console.error("delete tasks Error :", error);
    throw error;
  }
}

//-------------------------favorite-------------------------------
export async function favoriteTask(taskId: number) {
  try {
    const response = await axiosInstance1.put(
      `${endpoints.task.favorite}/${taskId}`
    );
    const newData = await response.data;
    mutate(endpoints.task.list);
    return newData;
  } catch (error) {
    console.error("Favorite task error:", error);
    throw error;
  }
}

export async function unfavoriteTask(taskId: number) {
  try {
    const response = await axiosInstance1.put(
      `${endpoints.task.unfavorit}/${taskId}`
    );
    const newData = await response.data;
    mutate(endpoints.task.list);
    return newData;
  } catch (error) {
    console.error("Unfavorite task error:", error);
    throw error;
  }
}

export async function unfavoritListTask(taskIds: number[]) {
  try {
    const unfavoritPromises = taskIds.map(async (taskId) => {
      await unfavoriteTask(taskId);
    });
    await Promise.all(unfavoritPromises);
    mutate(endpoints.task.list);
    return unfavoritPromises;
  } catch (error) {
    console.error("Unfavorite tasks error :", error);
    throw error;
  }
}

export function useGetCollaboratorsOfProject(projectId: number) {
  const URL = `${endpoints.project.collaboratorOfProject}/${projectId}`;
  const fetcherWithAuth = async (url: string) => {
    try {
      const token = localStorage.getItem("token");
      if (!token) {
        throw new Error("No authentication token found");
      }
      const response = await axios.get(url, {
        headers: {
          Authorization: `Bearer ${token}`,
          "Content-Type": "application/json",
        },
      });

      return response.data;
    } catch (error) {
      console.error("Error fetching collaborators:", error);
      throw error;
    }
  };

  // Use SWR to fetch data
  const { data, isLoading, error, isValidating } = useSWR<collaborator[]>(
    URL,
    fetcherWithAuth
  );

  // Memoize the derived state for performance optimization
  const memoizedValue = useMemo(
    () => ({
      collaborators1: (data as collaborator[]) || [],
      collaborators1Loading: isLoading,
      collaborators1Error: error,
      collaborators1Validating: isValidating,
      collaborators1Empty: !isLoading && !data?.length,
    }),
    [data, error, isLoading, isValidating]
  );

  return memoizedValue;
}

export function useGetManager(collabId: number) {
  const URL = `${endpoints.project.collaborator}/${collabId}`;
  const { data, isLoading, error } = useSWR<collaborator>(URL, fetcher1);
  return {
    managerData: data as collaborator,
    managerIsLoading: isLoading,
    managerError: error,
  };
}

export function useGetCollaborator(collabId: number) {
  const URL = `${endpoints.project.collaborator}/${collabId}`;
  const { data, isLoading, error } = useSWR<collaborator>(URL, fetcher1);
  return {
    collaborator: data as collaborator,
    collaboratorIsLoading: isLoading,
    collaboratorError: error,
  };
}

export function useGetParticipants(collabIds: number[]) {
  const fetchCollaborators = async () => {
    const promises = collabIds.map((id) =>
      fetcher1(`${endpoints.project.collaborator}/${id}`)
    );
    const results = await Promise.all(promises);
    return results as collaborator[];
  };
  const { data, error } = useSWR(
    collabIds.length ? `/collaborators/${collabIds.join(",")}` : null,
    fetchCollaborators
  );

  return {
    participants: data,
    isLoading: !error && !data,
    error,
  };
}

export async function addSubTask(taskId: number, subTask: IUnderTask) {
  try {
    const response = await axios.post(
      `${endpoints.task.subTask}/${taskId}/add`,
      subTask,
      {
        headers: {
          "Content-Type": "application/json",
        },
      }
    );
    return response.data;
  } catch (error) {
    console.error("Failed to add subtask:", error);
    throw error;
  }
}

export async function getSubTasksByTaskId(
  taskId: number
): Promise<IUnderTask[]> {
  try {
    const response = await axios.get(
      `${endpoints.task.subTask}/${taskId}/subtasks`
    );
    return response.data;
  } catch (error) {
    console.error("Failed to get subtasks:", error);
    throw error;
  }
}

export async function updateSubTask(
  subtaskId: number,
  updatedSubTask: IUnderTask
): Promise<IUnderTask> {
  try {
    const response = await axios.put(
      `${endpoints.task.subTask}/${subtaskId}/update`,
      updatedSubTask,
      {
        headers: {
          "Content-Type": "application/json",
        },
      }
    );
    return response.data;
  } catch (error) {
    console.error("Failed to update subtask:", error);
    throw error;
  }
}

export async function deleteSubTask(subtaskId: number): Promise<void> {
  try {
    await axios.delete(`${endpoints.task.subTask}/${subtaskId}/delete`);
  } catch (error) {
    console.error("Failed to delete subtask:", error);
    throw error;
  }
}

export async function assignSubTaskToCollaborator(
  subTaskId: number,
  collaboratorId: number
): Promise<IUnderTask> {
  try {
    const response = await axios.put(
      `${endpoints.task.subTask}/${subTaskId}/assign`,
      null,
      {
        params: { collaboratorId },
      }
    );
    return response.data;
  } catch (error) {
    console.error("Failed to assign collaborator to subtask:", error);
    throw error;
  }
}

export async function toggleCollaborator(
  taskId: number,
  collaboratorId: number
): Promise<any> {
  try {
    const response = await axios.put(
      `${endpoints.project.list}/${taskId}/toggle-collaborator`,
      null,
      {
        params: { collaboratorId },
      }
    );
    return response.data;
  } catch (error) {
    console.error("Failed to toggle collaborator:", error);
    throw error;
  }
}
