const configuredApiUrl = process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:4000";

function isLoopbackHost(hostname: string) {
  return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1";
}

function isPrivateLanHost(hostname: string) {
  return /^(10|192\.168)\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(hostname) || /^172\.(1[6-9]|2\d|3[0-1])\.\d{1,3}\.\d{1,3}$/.test(hostname);
}

function resolveApiUrl() {
  if (typeof window === "undefined") return configuredApiUrl;
  if (!configuredApiUrl || configuredApiUrl === "same-origin") return "";
  const configured = new URL(configuredApiUrl);
  const windowIsPrivate = isPrivateLanHost(window.location.hostname);
  const configuredIsLoopback = isLoopbackHost(configured.hostname);
  const configuredIsPrivate = isPrivateLanHost(configured.hostname);
  if (windowIsPrivate && configuredIsLoopback) {
    return `${window.location.protocol}//${window.location.hostname}:4000`;
  }
  if (!isLoopbackHost(window.location.hostname) && !windowIsPrivate && (configuredIsLoopback || configuredIsPrivate)) {
    return "";
  }
  return configuredApiUrl;
}

export const API_URL = resolveApiUrl();
const SESSION_TOKEN_KEY = "inventory_session_token";

export function saveSessionToken(token?: string) {
  if (typeof window === "undefined" || !token) return;
  window.localStorage.setItem(SESSION_TOKEN_KEY, token);
}

export function clearSessionToken() {
  if (typeof window === "undefined") return;
  window.localStorage.removeItem(SESSION_TOKEN_KEY);
}

export async function api<T>(path: string, options: RequestInit = {}): Promise<T> {
  const controller = new AbortController();
  const timeout = window.setTimeout(() => controller.abort(), 12000);
  const headers = new Headers(options.headers);
  if (options.body !== undefined && !headers.has("content-type")) {
    headers.set("content-type", "application/json");
  }
  const sessionToken = typeof window === "undefined" ? undefined : window.localStorage.getItem(SESSION_TOKEN_KEY);
  if (sessionToken && !headers.has("authorization")) {
    headers.set("authorization", `Bearer ${sessionToken}`);
  }
  const response = await fetch(`${API_URL}${path}`, {
    ...options,
    credentials: "include",
    signal: options.signal ?? controller.signal,
    headers
  }).catch((error) => {
    if (error instanceof DOMException && error.name === "AbortError") {
      throw new Error("Request timed out. Check that the server is running, then try again.");
    }
    throw error;
  }).finally(() => window.clearTimeout(timeout));

  const text = await response.text();
  const data = text ? JSON.parse(text) : {};
  if (!response.ok) {
    throw Object.assign(new Error(data.error ?? "Request failed"), { data, status: response.status });
  }
  return data as T;
}

export function idempotencyKey(prefix: string) {
  return `${prefix}-${crypto.randomUUID()}`;
}

export type Part = {
  id: string;
  name: string;
  sku: string | null;
  type: "base" | "partial" | "full";
  average_cost: string;
};

export type Location = {
  id: string;
  name: string;
  kind: "warehouse" | "truck" | "other";
};

export type InventoryRow = {
  partId: string;
  partName: string;
  sku: string | null;
  partType: "base" | "partial" | "full";
  averageCost: string;
  locationId: string;
  locationName: string;
  quantity: string;
  minQuantity: string | null;
};

export type TransactionRow = {
  id: string;
  createdAt: string;
  quantityDelta: string;
  unitCost: string;
  action: string;
  operationId: string;
  partName: string;
  locationName: string;
  userEmail: string | null;
};

export type BomComponentRow = {
  componentPartId: string;
};
