/**
 * Server-only fetch service.
 * Import as: import { serverFetch } from '@/lib/api/server'
 *
 * Use this in Server Components and Server Actions — never in client components.
 * All errors throw ApiError; callers decide whether to notFound(), redirect(), or surface an error boundary.
 */
import { headers } from 'next/headers';

import { API_URL } from '@/config';
import { COOKIE_NAMES } from '@/lib/cookies';
import { HEADER_NAMES } from '@/constants';
import { getServerCookie } from '@/lib/cookies/server';
import { ApiError } from './errors';

async function parseBody(response: Response): Promise<{ message?: string; code?: string }> {
  try {
    return await response.json();
  } catch {
    return {};
  }
}

export async function serverFetch<T>(path: string, options?: RequestInit): Promise<T> {
  const token = await getServerCookie(COOKIE_NAMES.ACCESS_TOKEN);

  let locale = 'fa';
  try {
    const reqHeaders = await headers();
    locale = reqHeaders.get(HEADER_NAMES.LOCALE) ?? 'fa';
  } catch {
    // Outside request context (build-time prerendering) — use default locale
  }

  const reqHeaders: Record<string, string> = {
    'Content-Type': 'application/json',
    'Accept-Language': locale,
  };
  if (token) {
    reqHeaders['Authorization'] = `Bearer ${token}`;
  }

  let response: Response;
  try {
    response = await fetch(`${API_URL}${path}`, {
      cache: 'no-store',
      ...options,
      headers: { ...reqHeaders, ...(options?.headers as Record<string, string>) },
    });
  } catch {
    throw new ApiError(0, 'Network error');
  }

  if (response.ok) {
    if (response.status === 204) return undefined as T;
    return response.json() as Promise<T>;
  }

  const body = await parseBody(response);
  throw new ApiError(response.status, body.message ?? response.statusText, body.code);
}
