import { getConfig } from "./config";
import type { Project, Task } from "./types";

class ApiError extends Error {
  constructor(public status: number, message: string) {
    super(message);
  }
}

async function req<T>(path: string, init?: RequestInit): Promise<T> {
  const { url, token } = await getConfig();
  if (!token) throw new ApiError(401, "No API token set — open Settings");
  const res = await fetch(`${url}${path}`, {
    ...init,
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
      ...init?.headers,
    },
  });
  if (!res.ok) {
    const body = await res.json().catch(() => ({ error: res.statusText }));
    throw new ApiError(res.status, (body as { error?: string }).error ?? `HTTP ${res.status}`);
  }
  return res.json();
}

export const api = {
  tasks: {
    list: (params: { status?: string; project_id?: string } = {}) => {
      const q = new URLSearchParams(
        Object.entries(params).filter(([, v]) => v != null) as [string, string][],
      ).toString();
      return req<Task[]>(`/v1/tasks${q ? `?${q}` : ""}`);
    },
    get: (id: string) => req<Task>(`/v1/tasks/${id}`),
    create: (data: Partial<Task> & { title: string; id?: string }) =>
      req<Task>("/v1/tasks", { method: "POST", body: JSON.stringify(data) }),
    update: (id: string, data: Partial<Task>) =>
      req<Task>(`/v1/tasks/${id}`, { method: "PATCH", body: JSON.stringify(data) }),
    trash: (id: string) => req<Task>(`/v1/tasks/${id}`, { method: "DELETE" }),
  },
  projects: {
    list: () => req<Project[]>("/v1/projects"),
    create: (data: Partial<Project> & { name: string; id?: string }) =>
      req<Project>("/v1/projects", { method: "POST", body: JSON.stringify(data) }),
    update: (id: string, data: Partial<Project>) =>
      req<Project>(`/v1/projects/${id}`, { method: "PATCH", body: JSON.stringify(data) }),
    drop: (id: string) => req<Project>(`/v1/projects/${id}`, { method: "DELETE" }),
  },
  contexts: { list: () => req<string[]>("/v1/contexts") },
};
