import { API_BASE_URL, TOKEN_NAME } from "@/configs";
import { privateInstance, publicInstance } from "@/configs/axiosConfig";
import { storage } from "@/configs/storage";
import { showToast } from "@/utils/toast";
import { useMutation } from "@tanstack/react-query";
import { useState } from "react";

interface MutateProps {
  isPublic?: boolean;
  url: string;
  config?: any;
  isUpdateMethod?: boolean;
}

const postFormData = async (url: string, body: FormData, isPublic: boolean) => {
  const headers: Record<string, string> = {
    Accept: "application/json",
    "mobile-app-key": process.env.EXPO_PUBLIC_MOBILE_APP_KEY ?? "",
  };

  if (!isPublic) {
    const token = storage.getString(TOKEN_NAME);
    if (token) headers["Authorization"] = `Bearer ${token}`;
  }

  console.log("📤 Sending request to:", url);
  console.log("📦 Request body: FormData");

  const response = await fetch(`${API_BASE_URL}${url}`, {
    method: "POST",
    headers,
    body,
  });

  const data = await response.json();
  console.log("✅ Response:", data);

  if (!response.ok) {
    const error = new Error(data?.message ?? "Request failed");
    (error as any).response = { status: response.status, data };
    throw error;
  }

  return data;
};

export const useQueryMutation = ({ isPublic = false, url, config = {}, isUpdateMethod = false }: MutateProps) => {
  const [backendErrors, setBackendErrors] = useState<any>(null);

  const postData = async (body: any) => {
    const isFormData = body instanceof FormData;

    if (isUpdateMethod) {
      if (isFormData) {
        body.append("_method", "PUT");
      } else {
        body = { ...body, _method: "PUT" };
      }
    }

    let requestUrl = url;
    if (!isFormData && body?.updatedUrl) {
      requestUrl = body.updatedUrl;
      delete body.updatedUrl;
    }

    if (isFormData) {
      return postFormData(requestUrl, body, isPublic);
    }

    console.log("📤 Sending request to:", requestUrl);
    console.log("📦 Request body:", body);

    try {
      const requestConfig: any = {
        ...config,
        headers: {
          ...config.headers,
        },
        validateStatus: (status: number) => status >= 200 && status < 500,
      };

      const response = await (isPublic ? publicInstance : privateInstance).post(requestUrl, body, requestConfig);

      console.log("✅ Response:", response.data);

      if (response.status >= 400) {
        const error = new Error(response.data?.message);
        (error as any).response = response;
        return Promise.reject(error);
      }

      return response.data;
    } catch (err: any) {
      console.log("❌ Request failed");
      console.log("Status:", err?.response?.status);
      console.log("StatusText:", err?.response?.statusText);
      console.log("Error Data:", err?.response?.data);
      console.log("Error Message:", err?.message);
      return Promise.reject(err);
    }
  };

  const { mutate, isError, isPending } = useMutation({
    mutationFn: postData,
    onSuccess: () => setBackendErrors(null),
    onError: (err: any) => {
      const status = err?.response?.status;
      const responseData = err?.response?.data;

      const nonCriticalStatuses = [
        417, // Email already verified
        419, // Token expired
      ];

      if (status === 422) {
        const formattedErrors = responseData?.errors
          ? Object.fromEntries(Object.entries(responseData.errors).map(([key, value]: [string, any]) => [key, Array.isArray(value) ? value[0] : value]))
          : responseData;
        console.log("📋 Formatted backend errors:", formattedErrors);
        setBackendErrors(formattedErrors);
      } else if (nonCriticalStatuses.includes(status)) {
        const message = responseData?.message || err?.message;
        console.log(`ℹ️ API Status ${status}:`, message);
        if (message) {
          showToast({ text: message, type: "error" });
        }
        setBackendErrors(null);
      } else {
        console.error("Mutation error:", err);
        setBackendErrors(null);
      }
    },
  });

  return {
    mutate,
    isError,
    isLoading: isPending,
    backendErrors,
  };
};
