import type { CursorPage, Health, Job, JobEvent, JobStats, LimitOffsetPage } from "./types";

const API_BASE_URL = import.meta.env.VITE_API_BASE_URL ?? "http://localhost:8000/api";

async function request<T>(path: string, init?: RequestInit): Promise<T> {
  const url = /^https?:\/\//i.test(path) ? path : `${API_BASE_URL}${path}`;
  const response = await fetch(url, {
    headers: { "Content-Type": "application/json", ...(init?.headers ?? {}) },
    ...init
  });
  if (!response.ok) {
    const body = await response.text();
    throw new Error(body || response.statusText);
  }
  return response.json() as Promise<T>;
}

export type CreateJobBody = {
  type: string;
  payload?: Record<string, unknown>;
  priority?: number;
  available_at?: string | null;
  max_attempts?: number;
  idempotency_key?: string | null;
};

function normalizeCursorPage<T>(value: CursorPage<T> | T[]): CursorPage<T> {
  if (Array.isArray(value)) {
    return { next: null, previous: null, results: value };
  }
  return value;
}

function normalizeLimitOffsetPage<T>(value: LimitOffsetPage<T> | T[]): LimitOffsetPage<T> {
  if (Array.isArray(value)) {
    return { count: value.length, next: null, previous: null, results: value };
  }
  return value;
}

export const api = {
  health: () => request<Health>("/health/"),
  listJobs: () => api.listJobsPage({ limit: 100 }).then((page) => page.results),
  listJobsPage: (filters: { limit?: number; offset?: number; status?: string; type?: string } = {}) => {
    const params = new URLSearchParams();
    Object.entries(filters).forEach(([key, value]) => {
      if (value !== undefined && value !== null && value !== "") params.set(key, String(value));
    });
    const query = params.toString();
    return request<LimitOffsetPage<Job> | Job[]>(`/jobs/${query ? `?${query}` : ""}`).then(normalizeLimitOffsetPage);
  },
  getJob: (jobId: string) => request<Job>(`/jobs/${jobId}/`),
  createJob: (body: CreateJobBody) => request<Job>("/jobs/", { method: "POST", body: JSON.stringify(body) }),
  retryJob: (jobId: string) => request<Job>(`/jobs/${jobId}/retry/`, { method: "POST" }),
  getStats: () => request<JobStats>("/jobs/stats/"),
  listJobEvents: (jobId: string) => request<JobEvent[]>(`/jobs/${jobId}/events/`),
  listEvents: (filters: { limit?: number; job_id?: string; type?: string } = {}) => {
    const params = new URLSearchParams();
    Object.entries(filters).forEach(([key, value]) => {
      if (value !== undefined && value !== null && value !== "") params.set(key, String(value));
    });
    const query = params.toString();
    return request<CursorPage<JobEvent> | JobEvent[]>(`/job-events/${query ? `?${query}` : ""}`).then(normalizeCursorPage);
  },
  listEventsPage: (url: string) => request<CursorPage<JobEvent> | JobEvent[]>(url).then(normalizeCursorPage)
};
