// API configuration and utility functions
/**
 * Base URL for images and static assets.
 * This is automatically prepended to image paths in language JSON files (en.json, sp.json)
 * by the useLanguage hook's replaceUrlsInTranslations function.
 *
 * Example: "/images/fe/studio.png" becomes "{IMAGE_BASE_URL}/images/fe/studio.png"
 */

import { logger } from "~/lib/logger";

const normalizeBaseUrl = (url: string): string => url.replace(/\/+$/, "");

const getEnv = (key: string): string =>
  (typeof process !== 'undefined' && process.env?.[key]) ||
  import.meta.env[key] ||
  '';

export const IMAGE_BASE_URL = normalizeBaseUrl(
  getEnv('VITE_IMAGE_BASE_URL') || "/",
);

export const API_BASE_URL = normalizeBaseUrl(
  getEnv('VITE_API_BASE_URL') || `${IMAGE_BASE_URL}/api`,
);

// Types for API responses
export interface AuthResponse {
  status: boolean;
  token?: string;
  user?: {
    uuid: string;
    fname: string;
    lname: string;
    email: string;
    role: string;
  };
  expires_in?: number;
  error?: string;
  message?: string;
  mobile_number?: string; // For forgot password response
  uuid?: string; // For signup response
}

export interface LogoutResponse {
  status: boolean;
  message?: string;
  error?: string;
}

export interface OTPResponse {
  status: boolean;
  message?: string;
  error?: string;
}

export interface Studio {
  id: number;
  name: string;
  studio_type: string;
  banner_picture: string;
  description: string;
}

export interface Person {
  uuid: string;
  fname: string;
  lname: string;
  profile_pic: string;
  type: string;
  location: string;
  profile_link: string | null;
  instagram_link: string | null;
  facebook_link: string | null;
  twitter_link: string | null;
  sm_link: string | null;
  description: string;
  languages_spoken?: string | string[] | null;
}

export interface Event {
  event_id: number;
  location_id: number;
  user_uuid: string;
  event_type: "online" | "location";
  public_private: "public" | "private";
  stream_url: string | null;
  event_title: string;
  event_date: string;
  event_time: string;
  duration: string | null;
  address: string;
  ticket_price: number;
  ticket_url: string | null;
  thumbnail: string;
  picture?: string;
  description: string;
  event_status: number;
  created_by: number;
  updated_by: number | null;
  created_at: string;
  updated_at: string;
  channel_arn: string | null;
  stream_arn: string | null;
  playbackurl: string | null;
  stream_key: string | null;
  interested_count: number;
  going_count: number;
}

export interface News {
  id: number;
  location_id: number;
  name: string;
  tags: string;
  banner: string;
  heading_intro: string;
  para_intro: string;
  heading_elaboration: string;
  para_elaboration: string;
  conclusion_picture: string;
  heading_conclusion: string | null;
  para_conclusion: string | null;
  status: number;
  created_by: {
    id: number;
    fname: string;
    lname: string;
  };
  updated_by: number;
  created_at: string;
  updated_at: string;
  thumbnail: string;
  slug?: string;
}

export interface APIResponse<T> {
  status: boolean;
  data?: T;
  error?: string;
}

export interface Location {
  id: number;
  location: string;
  type?: string;
  coming_soon?: number;
  banner_picture?: string;
  description?: string;
}

export interface Plan {
  id: number;
  name: string;
  slug: string;
  stripe_plan: string;
  price: number;
  frequency: string;
  points: number;
  num_of_guest: number;
  advance_duration: number;
  advance_frequency: string;
  created_at: string;
  updated_at: string | null;
  discounted_points?: number | string;
  tagline?: string;
  body?: string;
}

export interface Service {
  id: number;
  name: string;
  slug: string;
  description: string;
  frequency: string;
  price: string;
  status: number;
  stripe_plan: string;
  stripe_product: string;
  created_at: string;
  updated_at: string | null;
}

export interface PlansResponse {
  status: boolean;
  data: {
    plans: Plan[];
    services: Service;
  };
}

export interface Reservation {
  id: number;
  date: string;
  location: string;
  studio: string;
  price: number;
  image: string;
  [key: string]: any;
}

export interface GuestInvitation {
  id: number;
  host_uuid: string;
  guest_name: string;
  date: string;
  location: string;
  image: string;
  my_guest_or_by: string;
  [key: string]: any;
}

// Check if token is expired
const isTokenExpired = (): boolean => {
  if (typeof window !== "undefined") {
    const expirationTime = localStorage.getItem("tokenExpiration");
    if (expirationTime) {
      return Date.now() >= parseInt(expirationTime, 10);
    }
  }
  return false;
};

// Get auth token from localStorage (migrates legacy keys on first read)
export const getAuthToken = (): string | null => {
  if (typeof window !== "undefined") {
    if (isTokenExpired()) {
      removeAuthToken();
      return null;
    }
    let token = localStorage.getItem("auth_token");
    if (!token) {
      token = localStorage.getItem("authToken") || localStorage.getItem("token");
      if (token) {
        localStorage.setItem("auth_token", token);
        localStorage.removeItem("authToken");
        localStorage.removeItem("token");
      }
    }
    return token;
  }
  return null;
};

// Set auth token in localStorage
export const setAuthToken = (token: string): void => {
  if (typeof window !== "undefined") {
    localStorage.setItem("auth_token", token);
    localStorage.removeItem("authToken");
    localStorage.removeItem("token");
  }
};

// Remove auth token from localStorage
export const removeAuthToken = (): void => {
  if (typeof window !== "undefined") {
    localStorage.removeItem("auth_token");
    localStorage.removeItem("authToken");
    localStorage.removeItem("token");
    localStorage.removeItem("user_data");
    localStorage.removeItem("tokenExpiration");
    localStorage.removeItem("userFullResponse");
  }
};

// Store user data
export const setUserData = (user: any): void => {
  if (typeof window !== "undefined") {
    localStorage.setItem("user_data", JSON.stringify(user));
  }
};

// Get user data
export const getUserData = (): any => {
  if (typeof window !== "undefined") {
    const userData = localStorage.getItem("user_data");
    return userData ? JSON.parse(userData) : null;
  }
  return null;

  // BYPASS LOGIN FOR TESTING (commented out):
  // return {
  //   fname: 'John',
  //   lname: 'Doe',
  //   email: 'john.doe@example.com',
  //   uuid: 'test-user-123'
  // };
};

// Generic API request function
async function apiRequest<T>(
  endpoint: string,
  options: RequestInit = {},
): Promise<T> {
  try {
    const token = getAuthToken();

    // Check if body is FormData - if so, don't set Content-Type (let browser set it with boundary)
    const isFormData = options.body instanceof FormData;

    const defaultHeaders: Record<string, string> = {};

    // Only set Content-Type and Accept for non-FormData requests
    if (!isFormData) {
      defaultHeaders["Content-Type"] = "application/json";
      defaultHeaders.Accept = "application/json";
    }

    if (token) {
      defaultHeaders.Authorization = `Bearer ${token}`;
    }

    // For SSO auto-login the backend expects the endpoint without the `/api` prefix.
    // If the endpoint contains `auto-login`, strip a trailing `/api` from the base URL.
    let requestBase = API_BASE_URL;
    if (endpoint && endpoint.includes("auto-login")) {
      requestBase = requestBase.replace(/\/api\/?$/i, "");
    }

    const requestUrl = `${requestBase}${endpoint}`;
    logger.log(`Making API request to: ${requestUrl}`);

    const response = await fetch(requestUrl, {
      ...options,
      headers: {
        ...defaultHeaders,
        ...options.headers,
      },
    });

    logger.log(`API Response status: ${response.status}`, response);

    // Check if response is JSON
    const contentType = response.headers.get("content-type");
    if (!contentType || !contentType.includes("application/json")) {
      const textData = await response.text();
      logger.error("Non-JSON response received:", textData.substring(0, 500));
      throw new Error(
        `API returned non-JSON response. This might be a network or access issue.`,
      );
    }

    const data = await response.json();
    logger.log(`API Response data:`, data);

    if (!response.ok) {
      // Check for 401 Unauthorized (expired token)
      if (response.status === 401) {
        logger.log(
          "401 Unauthorized - Token expired or invalid, clearing localStorage",
        );
        removeAuthToken();
        // Optionally redirect to login
        if (
          typeof window !== "undefined" &&
          !window.location.pathname.includes("/login")
        ) {
          window.location.href = "/login";
        }
      }

      // Format error message from response
      let errorMessage = `HTTP error! status: ${response.status}`;
      if (data.error) {
        if (typeof data.error === "string") {
          errorMessage = data.error;
        } else if (typeof data.error === "object") {
          // Handle validation errors like {"email": ["The email has already been taken."]}
          const errors = Object.values(data.error).flat();
          errorMessage = errors.join(", ");
        }
      } else if (data.message) {
        errorMessage = data.message;
      }

      throw new Error(errorMessage);
    }

    return data;
  } catch (error) {
    logger.error(`API request failed for ${endpoint}:`, error);
    // Re-throw with more context
    if (error instanceof Error) {
      throw error; // Don't wrap again, preserve the formatted message
    }
    throw new Error(`Unknown API error occurred`);
  }
}

// Authentication APIs
export const authAPI = {
  // Email/Password Login
  login: async (email: string, password: string): Promise<AuthResponse> => {
    return apiRequest<AuthResponse>("/login", {
      method: "POST",
      body: JSON.stringify({ email, password }),
    });
  },

  // Send OTP to mobile number
  sendOTP: async (mobile_number: string): Promise<OTPResponse> => {
    return apiRequest<OTPResponse>("/send-otp", {
      method: "POST",
      body: JSON.stringify({ mobile_number }),
    });
  },

  // Verify OTP and login
  verifyOTP: async (
    mobile_number: string,
    otp_number: string,
    request_type: string = "login",
    additionalData?: {
      fname?: string;
      lname?: string;
      email?: string;
      plan?: string;
      addon_services?: string[];
      password?: string;
      confirm_password?: string;
      privacy_policy_version?: string;
      privacy_policy_accepted_ip?: string;
      terms_version?: string;
      guardian_email?: string;
    },
  ): Promise<AuthResponse> => {
    const payload: any = {
      request_type,
      otp_number,
      mobile_number,
    };

    // Add additional data if provided
    if (additionalData) {
      Object.assign(payload, additionalData);
    }

    logger.log("verifyOTP payload:", payload);

    return apiRequest<AuthResponse>("/verify-otp", {
      method: "POST",
      body: JSON.stringify(payload),
    });
  },

  // Logout
  logout: async (): Promise<LogoutResponse> => {
    return apiRequest<LogoutResponse>("/logout", {
      method: "POST",
    });
  },

  // Forgot Password - Send OTP to mobile
  forgotPassword: async (email: string): Promise<AuthResponse> => {
    return apiRequest<AuthResponse>("/forgot-password", {
      method: "POST",
      body: JSON.stringify({ email }),
    });
  },

  // Reset Password
  resetPassword: async (email: string): Promise<AuthResponse> => {
    return apiRequest<AuthResponse>("/reset-password", {
      method: "POST",
      body: JSON.stringify({ email }),
    });
  },

  // Save Profile Picture
  saveProfilePicture: async (
    uuid: string,
    file: File,
  ): Promise<AuthResponse> => {
    // Get the signup token from localStorage
    const signupToken =
      typeof window !== "undefined"
        ? localStorage.getItem("signup_token")
        : null;

    // Create FormData
    const formData = new FormData();
    formData.append("type", "profile");
    formData.append("file", file);

    const headers: HeadersInit = {};

    // Add Authorization header if token exists
    if (signupToken) {
      headers["Authorization"] = `Bearer ${signupToken}`;
    }

    // Don't set Content-Type, let the browser set it with boundary for multipart/form-data
    return apiRequest<AuthResponse>("/save-profile-picture", {
      method: "POST",
      headers,
      body: formData,
    });
  },

  // Save Additional Information
  saveAdditionalInfo: async (data: {
    uuid: string;
    home_city: string;
    creator_interest?: string[];
    profile_link?: string;
    instagram_link?: string;
    facebook_link?: string;
    twitter_link?: string;
    sm_link?: string;
    referred_by?: string;
  }): Promise<AuthResponse> => {
    // Get the signup token from localStorage
    const signupToken =
      typeof window !== "undefined"
        ? localStorage.getItem("signup_token")
        : null;

    const headers: HeadersInit = {
      "Content-Type": "application/json",
    };

    // Add Authorization header if token exists
    if (signupToken) {
      headers["Authorization"] = `Bearer ${signupToken}`;
    }

    return apiRequest<AuthResponse>("/additional-info-save", {
      method: "POST",
      headers,
      body: JSON.stringify(data),
    });
  },

  // Add Payment Method during signup
  addPaymentMethod: async (data: {
    name: string;
    token: string;
    type?: string;
  }): Promise<AuthResponse> => {
    // Get the signup token from localStorage
    const signupToken =
      typeof window !== "undefined"
        ? localStorage.getItem("signup_token")
        : null;

    const formData = new FormData();
    formData.append("name", data.name);
    formData.append("token", data.token);
    formData.append("type", data.type || "signup");

    const headers: HeadersInit = {};

    // Add Authorization header if token exists
    if (signupToken) {
      headers["Authorization"] = `Bearer ${signupToken}`;
    }

    return apiRequest<AuthResponse>("/add-payment-method", {
      method: "POST",
      headers,
      body: formData,
    });
  },
};

// Locations API
export const locationsAPI = {
  // Get all locations
  getLocations: async (): Promise<APIResponse<Location[]>> => {
    return apiRequest<APIResponse<Location[]>>("/locations", {
      method: "GET",
    });
  },
};

// Studios API
export const studiosAPI = {
  getByLocation: async (locationId: number): Promise<APIResponse<Studio[]>> => {
    return apiRequest<APIResponse<Studio[]>>(`/studios/${locationId}`);
  },
};

// People API
export const peopleAPI = {
  getAll: async (): Promise<APIResponse<Person[]>> => {
    return apiRequest<APIResponse<Person[]>>("/peoples");
  },
};

// Events API
export const eventsAPI = {
  getAll: async (
    filterDate?: string,
    filterLocation?: number,
  ): Promise<APIResponse<Event[]>> => {
    const params = new URLSearchParams();
    if (filterDate) params.append("filterDate", filterDate);
    if (filterLocation)
      params.append("filterLocation", filterLocation.toString());

    const queryString = params.toString();
    const endpoint = queryString ? `/events?${queryString}` : "/events";

    return apiRequest<APIResponse<Event[]>>(endpoint);
  },

  getById: async (eventId: number): Promise<APIResponse<Event>> => {
    return apiRequest<APIResponse<Event>>(`/events/${eventId}`);
  },

  markInterested: async (eventId: number): Promise<APIResponse<any>> => {
    return apiRequest<APIResponse<any>>(`/event/interested/${eventId}`, {
      method: "POST",
    });
  },

  markGoing: async (eventId: number): Promise<APIResponse<any>> => {
    return apiRequest<APIResponse<any>>("/going-event", {
      method: "POST",
      body: JSON.stringify({ event_id: eventId }),
    });
  },
};

// News API
export const newsAPI = {
  getAll: async (
    filterDate?: string,
    filterTags?: string,
    filterLocation?: number,
  ): Promise<APIResponse<News[]>> => {
    const params = new URLSearchParams();
    if (filterDate) params.append("filterDate", filterDate);
    if (filterTags) params.append("filterTags", filterTags);
    if (filterLocation)
      params.append("filterLocation", filterLocation.toString());

    const queryString = params.toString();
    const endpoint = queryString ? `/news?${queryString}` : "/news";

    return apiRequest<APIResponse<News[]>>(endpoint);
  },

  getById: async (newsId: number): Promise<APIResponse<News>> => {
    return apiRequest<APIResponse<News>>(`/news/${newsId}`);
  },

  getBySlug: async (slug: string): Promise<APIResponse<News>> => {
    return apiRequest<APIResponse<News>>(`/news/slug/${slug}`);
  },
};

// Plans API
export const plansAPI = {
  getAll: async (): Promise<PlansResponse> => {
    // Use the specific plans API endpoint with port 444
    const plansUrl = `${API_BASE_URL}/plans`;
    try {
      const response = await fetch(plansUrl, {
        method: "GET",
        headers: {
          "Content-Type": "application/json",
          Accept: "application/json",
        },
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const data = await response.json();
      return data;
    } catch (error) {
      logger.error("Plans API error:", error);
      throw new Error(
        `Plans API Error: ${
          error instanceof Error ? error.message : "Unknown error"
        }`,
      );
    }
  },
};

// Upcoming Reservations API
export const reservationsAPI = {
  getUpcoming: async (limit?: number): Promise<APIResponse<Reservation[]>> => {
    const params = new URLSearchParams();
    if (limit) params.append("limit", limit.toString());

    const queryString = params.toString();
    const endpoint = queryString
      ? `/upcoming-reservations?${queryString}`
      : "/upcoming-reservations";

    return apiRequest<APIResponse<Reservation[]>>(endpoint);
  },
};

// Guest Invitations API
export const guestInvitationsAPI = {
  getAll: async (limit?: number): Promise<APIResponse<GuestInvitation[]>> => {
    const params = new URLSearchParams();
    if (limit) params.append("limit", limit.toString());

    const queryString = params.toString();
    const endpoint = queryString
      ? `/guest-invitations?${queryString}`
      : "/guest-invitations";

    return apiRequest<APIResponse<GuestInvitation[]>>(endpoint);
  },
  cancel: async (invitationId: string | number): Promise<APIResponse<any>> => {
    const endpoint = `/invitation-action`;
    const bodyPayload: any = {};
    bodyPayload.upcoming_id = invitationId;
    bodyPayload.status = 2;
    return apiRequest<APIResponse<any>>(endpoint, {
      method: "POST",
      body: JSON.stringify(bodyPayload),
    });
  },
  resend: async (invitationId: string | number): Promise<APIResponse<any>> => {
    const endpoint = `/invitation-action`;
    const bodyPayload: any = {};
    bodyPayload.upcoming_id = invitationId;
    bodyPayload.status = 3;
    return apiRequest<APIResponse<any>>(endpoint, {
      method: "POST",
      body: JSON.stringify(bodyPayload),
    });
  },
};

// Auto-login API: send token to server to validate and get redirected
export const autoLoginAPI = async (
  token: string,
): Promise<APIResponse<any>> => {
  try {
    // Don't use apiRequest wrapper to avoid automatic Authorization header
    // The auto-login endpoint expects only the token in the request body
    const requestBase = API_BASE_URL.replace(/\/api\/?$/i, "");
    const requestUrl = `${requestBase}/auto-login`;

    logger.log(`Making auto-login request to: ${requestUrl}`);

    const response = await fetch(requestUrl, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json",
      },
      body: JSON.stringify({ token }),
    });

    logger.log(`Auto-login response status: ${response.status}`, response);

    // Check if response is JSON
    const contentType = response.headers.get("content-type");
    if (!contentType || !contentType.includes("application/json")) {
      const textData = await response.text();
      logger.error(
        "Auto-login non-JSON response received:",
        textData.substring(0, 500),
      );
      throw new Error("Auto-login API returned non-JSON response");
    }

    const data = await response.json();
    logger.log("Auto-login response data:", data);

    if (!response.ok) {
      let errorMessage = `HTTP error! status: ${response.status}`;
      if (data.error) {
        errorMessage =
          typeof data.error === "string"
            ? data.error
            : JSON.stringify(data.error);
      } else if (data.message) {
        errorMessage = data.message;
      }
      throw new Error(errorMessage);
    }

    return data;
  } catch (error) {
    logger.error("Auto-login API request failed:", error);
    if (error instanceof Error) {
      throw error;
    }
    throw new Error("Unknown auto-login API error occurred");
  }
};

// Auth helper functions
export const isAuthenticated = (): boolean => {
  return getAuthToken() !== null;

  // BYPASS LOGIN FOR TESTING (commented out):
  // return true;
};

export const handleAuthSuccess = (response: AuthResponse): void => {
  if (response.token) {
    setAuthToken(response.token);
    logger.log("Auth token set");

    // Sync token to server-side cookie session for SSR loader access
    fetch("/api/sync-session", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ token: response.token }),
    }).catch((err) => logger.error("Session sync failed:", err));
  }
  if (response.user) {
    const userDataWithHomeCity = {
      ...response.user,
      home_city: (response as any).home_city,
    };
    setUserData(userDataWithHomeCity);
    logger.log("User data set with home_city:", (response as any).home_city);
  }

  if (response.expires_in && typeof window !== "undefined") {
    const expirationTime = Date.now() + response.expires_in * 1000;
    localStorage.setItem("tokenExpiration", expirationTime.toString());
  }

  if (typeof window !== "undefined") {
    localStorage.setItem("userFullResponse", JSON.stringify(response));

    if ((window as any).saveLoginResponse) {
      (window as any).saveLoginResponse(response);
    }
  }
};

export const handleLogout = async (): Promise<void> => {
  try {
    await authAPI.logout();
  } catch (error) {
    logger.error("Logout error:", error);
  } finally {
    removeAuthToken();
    // Destroy server-side cookie session
    fetch("/api/sync-session", { method: "DELETE" }).catch(() => {});
  }
};

// If the URL contains ?logout=true, clear auth token and related localStorage items.
if (typeof window !== "undefined") {
  try {
    const params = new URLSearchParams(window.location.search);
    if (params.get("logout") === "true") {
      removeAuthToken();
      try {
        localStorage.removeItem("tokenExpiration");
        localStorage.removeItem("userFullResponse");
      } catch (e) {
        // ignore localStorage errors
      }
    }
  } catch (e) {
    // ignore URL parsing errors
  }
}

// Payment method deletion function
export const deletePaymentMethod = async (
  pmid: string,
): Promise<{ status: boolean; message?: string }> => {
  try {
    const token = getAuthToken();

    const formData = new FormData();
    formData.append("pmid", pmid);

    const response = await fetch(`${API_BASE_URL}/payment-method-delete`, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${token}`,
      },
      body: formData,
    });

    const result = await response.json();

    return {
      status: response.ok && result.status,
      message:
        result.message ||
        (response.ok
          ? "Payment method deleted successfully"
          : "Failed to delete payment method"),
    };
  } catch (error) {
    logger.error("Delete payment method error:", error);
    return {
      status: false,
      message: "An error occurred while deleting the payment method",
    };
  }
};
