import Cookies from "js-cookie";


/**
 * Sends form data including multiple files and text fields
 * Supports both client-side token (legacy) and server-side HTTP-only token
 */
export const postFormData = async (formDataObj: { [key: string]: any }) => {
  const clientToken = Cookies.get("token");
  const formData = new FormData();

  for (const key in formDataObj) {
    const value = formDataObj[key];
    formData.append(key, value);
  }

  try {
    // If client-side token exists, use direct API call
    if (clientToken) {
      const response = await fetch(`${process.env.NEXT_PUBLIC_APP_URL}/co-creation/save`, {
        method: "POST",
        headers: {
          Authorization: `Bearer ${clientToken}`,
        },
        body: formData,
      });

      const data = await response.json();
      if (!response.ok) throw new Error(data.message || "Something went wrong");

      return data;
    } else {
      // Otherwise, use proxy API (server-side HTTP-only token)
      const response = await fetch(`/api/co-creation/save`, {
        method: "POST",
        credentials: 'include',
        body: formData,
      });

      const data = await response.json();
      if (!response.ok) throw new Error(data.message || "Something went wrong");

      return data;
    }
  } catch (error: any) {
    console.error("API Error:", error.message);
    throw error;
  }
};

/**
 * GET API client - supports both client-side token and server-side HTTP-only token
 */
export const getApiClient = async (
  endpoint: string,
  params: Record<string, any> = {},
  options: { requiresAuth?: boolean } = {},
) => {
  const { requiresAuth = true } = options;
  const clientToken = Cookies.get("token");
  
  try {
    // If client-side token exists, use direct API call with bearer token
    if (clientToken) {
      const url = new URL(`${process.env.NEXT_PUBLIC_APP_URL}/${endpoint}`);
      Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
      
      const response = await fetch(url.toString(), {
        method: "GET",
        headers: {
          Authorization: `Bearer ${clientToken}`,
        },
      });

      if (!response.ok) {
        const errorData = await response.json();
        throw new Error(errorData.message || "Failed to fetch data");
      }
      
      const data = await response.json();
      return data?.data;
    }

    // When auth is required, fall back to proxy that uses http-only token
    if (requiresAuth) {
      const url = new URL(`/api/proxy/${endpoint}`, window.location.origin);
      Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
      
      const response = await fetch(url.toString(), {
        method: "GET",
        credentials: 'include',
        headers: {
          'Content-Type': 'application/json',
        },
      });

      if (!response.ok) {
        const errorData = await response.json();
        throw new Error(errorData.message || "Failed to fetch data");
      }
      
      const data = await response.json();
      return data?.data;
    }

    // Public, no-auth call directly to API_BASE_URL
    const url = new URL(`${process.env.NEXT_PUBLIC_APP_URL}/${endpoint}`);
    Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));

    const response = await fetch(url.toString(), {
      method: "GET",
      headers: {
        'Content-Type': 'application/json',
      },
    });

    if (!response.ok) {
      const errorData = await response.json();
      throw new Error(errorData.message || "Failed to fetch data");
    }

    const data = await response.json();
    return data?.data;
  } catch (error: any) {
    console.error("API Error:", error.message);
    throw error;
  }
};

/**
 * POST API client for JSON data - supports both client-side token and server-side HTTP-only token
 */
export const postApiClient = async (endpoint: string, payload: Record<string, any> = {}) => {
  const clientToken = Cookies.get("token");
  
  try {
    // If client-side token exists, use direct API call
    if (clientToken) {
      const response = await fetch(`${process.env.NEXT_PUBLIC_APP_URL}/${endpoint}`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${clientToken}`,
        },
        body: JSON.stringify(payload),
      });

      const data = await response.json();
      
      if (!response.ok) {
        throw new Error(data.message || "Something went wrong");
      }

      return data;
    } else {
      // Otherwise, use proxy API (server-side HTTP-only token)
      const response = await fetch(`/api/proxy/${endpoint}`, {
        method: "POST",
        credentials: 'include',
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(payload),
      });

      const data = await response.json();
      
      if (!response.ok) {
        throw new Error(data.message || "Something went wrong");
      }

      return data;
    }
  } catch (error: any) {
    console.error("API Error:", error.message);
    throw error;
  }
};

/**
 * DELETE API client - supports both client-side token and server-side HTTP-only token
 */
export const deleteApiClient = async (endpoint: string, payload: Record<string, any> = {}) => {
  const clientToken = Cookies.get("token");
  
  try {
    // If client-side token exists, use direct API call
    if (clientToken) {
      const response = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/${endpoint}`, {
        method: "DELETE",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${clientToken}`,
        },
        body: JSON.stringify(payload),
      });

      const data = await response.json();
      
      if (!response.ok) {
        throw new Error(data.message || "Something went wrong");
      }

      return data;
    } else {
      // Otherwise, use proxy API (server-side HTTP-only token)
      const response = await fetch(`/api/proxy/${endpoint}`, {
        method: "DELETE",
        credentials: 'include',
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(payload),
      });

      const data = await response.json();
      
      if (!response.ok) {
        throw new Error(data.message || "Something went wrong");
      }

      return data;
    }
  } catch (error: any) {
    console.error("API Error:", error.message);
    throw error;
  }
};

/**
 * POST FormData API client - supports file uploads with both client-side token and server-side HTTP-only token
 * Use this for uploading files (images, documents, etc.)
 */
export const postFormDataClient = async (endpoint: string, formData: FormData) => {
  const clientToken = Cookies.get("token");
  
  try {
    // If client-side token exists, use direct API call
    if (clientToken) {
      const response = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/${endpoint}`, {
        method: "POST",
        headers: {
          Authorization: `Bearer ${clientToken}`,
        },
        body: formData,
      });

      // Check if response is a redirect (302) or not JSON
      if (response.status === 302 || response.redirected) {
        throw new Error("Authentication failed. Please login again.");
      }

      // Check content type before parsing
      const contentType = response.headers.get("content-type");
      if (!contentType || !contentType.includes("application/json")) {
        throw new Error(`Server returned ${response.status}: ${response.statusText}`);
      }

      const data = await response.json();
      
      if (!response.ok) {
        throw new Error(data.message || "Upload failed");
      }

      return data;
    } else {
      // Otherwise, use proxy API (server-side HTTP-only token)
      // Note: FormData through proxy needs special handling
      const response = await fetch(`/api/proxy/${endpoint}`, {
        method: "POST",
        credentials: 'include',
        body: formData,
      });

      // Check if response is a redirect
      if (response.status === 302 || response.redirected) {
        throw new Error("Authentication failed. Please login again.");
      }

      // Check content type before parsing
      const contentType = response.headers.get("content-type");
      if (!contentType || !contentType.includes("application/json")) {
        throw new Error(`Server returned ${response.status}: ${response.statusText}`);
      }

      const data = await response.json();
      
      if (!response.ok) {
        throw new Error(data.message || "Upload failed");
      }

      return data;
    }
  } catch (error: any) {
    console.error("FormData API Error:", error.message);
    throw error;
  }
};