import { Platform } from "react-native";
import { apiLogger } from "../logging";
import { useAuthStore } from "../stores";

const API_BASE_URL =
  process.env.EXPO_PUBLIC_API_URL ||
  Platform.select({
    android: "http://10.0.2.2:3001/api",
    default: "http://localhost:3001/api",
  });

type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";

interface RequestOptions {
  headers?: Record<string, string>;
  body?: unknown;
  skipAuth?: boolean;
}

function getAuthHeaders(): Record<string, string> {
  const user = useAuthStore.getState().user;
  apiLogger.debug(`getAuthHeaders - user: ${JSON.stringify(user)}`);
  if (user?.id) {
    return { "X-User-Id": user.id };
  }
  return {};
}

async function request<T>(
  method: HttpMethod,
  endpoint: string,
  options?: RequestOptions,
): Promise<T> {
  const start = performance.now();
  apiLogger.debug(`${method} ${endpoint}`);

  try {
    const authHeaders = options?.skipAuth ? {} : getAuthHeaders();

    const response = await fetch(`${API_BASE_URL}${endpoint}`, {
      method,
      headers: {
        "Content-Type": "application/json",
        ...authHeaders,
        ...options?.headers,
      },
      body: options?.body ? JSON.stringify(options.body) : undefined,
    });

    const duration = Math.round(performance.now() - start);

    if (!response.ok) {
      apiLogger.error(
        `${method} ${endpoint} - ${response.status} (${duration}ms)`,
      );
      throw new Error(`HTTP ${response.status}`);
    }

    apiLogger.debug(
      `${method} ${endpoint} - ${response.status} (${duration}ms)`,
    );

    const text = await response.text();
    if (!text) {
      return undefined as T;
    }
    return JSON.parse(text);
  } catch (error) {
    const duration = Math.round(performance.now() - start);
    apiLogger.error(`${method} ${endpoint} failed (${duration}ms): ${error}`);
    throw error;
  }
}

export const ApiClient = {
  get: async <T>(
    endpoint: string,
    options?: Omit<RequestOptions, "body">,
  ): Promise<T> => {
    return request<T>("GET", endpoint, options);
  },

  post: async <T>(
    endpoint: string,
    body?: unknown,
    options?: RequestOptions,
  ): Promise<T> => {
    return request<T>("POST", endpoint, { ...options, body });
  },

  put: async <T>(
    endpoint: string,
    body?: unknown,
    options?: RequestOptions,
  ): Promise<T> => {
    return request<T>("PUT", endpoint, { ...options, body });
  },

  delete: async <T>(
    endpoint: string,
    options?: Omit<RequestOptions, "body">,
  ): Promise<T> => {
    return request<T>("DELETE", endpoint, options);
  },
};

export { API_BASE_URL };
