import type { Repository, ChangeMeta, ChangeDetail, TreeEntry } from "@pijulab/shared";

const base = "/api";

async function request<T>(path: string, options?: RequestInit): Promise<T> {
  const res = await fetch(`${base}${path}`, {
    credentials: "include",
    headers: { "Content-Type": "application/json", ...options?.headers },
    ...options,
  });
  if (!res.ok) {
    const err = await res.json().catch(() => ({ message: res.statusText }));
    throw new Error((err as { message?: string }).message ?? "Request failed");
  }
  return res.json() as Promise<T>;
}

export interface AuthUser {
  id: number;
  username: string;
  email: string;
  displayName: string | null;
}

export const api = {
  auth: {
    signup: (body: { username: string; email: string; password: string }) =>
      request<AuthUser>("/auth/signup", { method: "POST", body: JSON.stringify(body) }),
    login: (body: { email: string; password: string }) =>
      request<AuthUser>("/auth/login", { method: "POST", body: JSON.stringify(body) }),
    logout: () => request<{ ok: boolean }>("/auth/logout", { method: "POST" }),
  },
  me: {
    get: () => request<AuthUser>("/me"),
    repos: () => request<Repository[]>("/me/repos"),
  },
  repos: {
    create: (body: { name: string; description?: string; visibility: "public" | "private" }) =>
      request<{ id: number; name: string }>("/repos", {
        method: "POST",
        body: JSON.stringify(body),
      }),
    get: (owner: string, name: string) => request<Repository>(`/repos/${owner}/${name}`),
    channels: (owner: string, name: string) =>
      request<string[]>(`/repos/${owner}/${name}/channels`),
    tree: (owner: string, name: string, channel: string, subpath = "") =>
      request<TreeEntry[]>(
        `/repos/${owner}/${name}/tree?channel=${channel}&path=${encodeURIComponent(subpath)}`,
      ),
    log: (owner: string, name: string, channel: string) =>
      request<ChangeMeta[]>(`/repos/${owner}/${name}/log?channel=${channel}`),
    change: (owner: string, name: string, hash: string) =>
      request<ChangeDetail>(`/repos/${owner}/${name}/change/${hash}`),
  },
};