const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000';

import { emitSessionExpired, shouldNotifySessionExpired } from '@/lib/sessionAuth';

export interface ApiOptions extends RequestInit {
  token?: string;
}

export class ApiError extends Error {
  status: number;
  constructor(message: string, status: number) {
    super(message);
    this.status = status;
  }
}

export async function api<T>(
  endpoint: string,
  options: ApiOptions = {}
): Promise<T> {
  const { token, ...fetchOptions } = options;

  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
    ...(options.headers as Record<string, string>),
  };

  if (token) {
    headers.Authorization = `Bearer ${token}`;
  } else if (typeof window !== 'undefined') {
    const stored = localStorage.getItem('accessToken');
    if (stored) headers.Authorization = `Bearer ${stored}`;
  }

  const res = await fetch(`${API_URL}/api${endpoint}`, {
    ...fetchOptions,
    headers,
    credentials: 'include',
  });

  const data = await res.json();

  if (!res.ok || !data.success) {
    if (shouldNotifySessionExpired(endpoint, res.status, Boolean(headers.Authorization))) {
      emitSessionExpired();
    }
    throw new ApiError(data.error || 'Request failed', res.status);
  }

  return data;
}

export function getUploadUrl(path: string) {
  if (path.startsWith('http')) return path;
  return `${API_URL}${path}`;
}

export async function uploadForm<T>(
  endpoint: string,
  formData: FormData,
  options: { method?: string } = {}
): Promise<T> {
  const headers: Record<string, string> = {};

  if (typeof window !== 'undefined') {
    const stored = localStorage.getItem('accessToken');
    if (stored) headers.Authorization = `Bearer ${stored}`;
  }

  const res = await fetch(`${API_URL}/api${endpoint}`, {
    method: options.method || 'POST',
    headers,
    body: formData,
    credentials: 'include',
  });

  const data = await res.json();

  if (!res.ok || !data.success) {
    if (shouldNotifySessionExpired(endpoint, res.status, Boolean(headers.Authorization))) {
      emitSessionExpired();
    }
    throw new ApiError(data.error || 'Upload failed', res.status);
  }

  return data;
}
