/**
 * Typed API client for the FamilySync lists API.
 *
 * credentials: 'include' is required so the OIDC session cookie is sent with
 * every request (same pattern as client.ts).
 *
 * Exports: fetchLists, createList, patchList, deleteList,
 *          fetchListItems, addItem, patchListItem, deleteItem
 * Types: List, ListItem, ListsResponse, ListItemsResponse
 */

const BASE = '/api';

async function apiFetch(path: string, init?: RequestInit): Promise<Response> {
  const res = await fetch(`${BASE}${path}`, {
    credentials: 'include',
    ...init,
  });
  if (!res.ok) throw new Error(`${init?.method ?? 'GET'} ${path} failed: ${res.status}`);
  return res;
}

// ── Types ──────────────────────────────────────────────────────────────────

export interface List {
  id: number;
  name: string;
  isShared: boolean;
  ownerId: number;
  activeCount: number;
  doneCount: number;
  createdAt?: string;
  updatedAt?: string;
}

export interface ListItem {
  id: number;
  listId: number;
  text: string;
  checked: boolean;
  rank: string;
  createdAt?: string;
  updatedAt?: string;
}

export interface ListsResponse {
  lists: List[];
}

export interface ListItemsResponse {
  items: ListItem[];
}

// ── Functions ──────────────────────────────────────────────────────────────

export async function fetchLists(): Promise<ListsResponse> {
  return apiFetch('/lists').then((r) => r.json() as Promise<ListsResponse>);
}

export async function createList(payload: { name: string; isShared: boolean }): Promise<List> {
  return apiFetch('/lists', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload),
  }).then((r) => r.json() as Promise<List>);
}

export async function patchList(
  id: number,
  patch: { name?: string; isShared?: boolean },
): Promise<List> {
  return apiFetch(`/lists/${id}`, {
    method: 'PATCH',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(patch),
  }).then((r) => r.json() as Promise<List>);
}

export async function deleteList(id: number): Promise<{ id: number }> {
  return apiFetch(`/lists/${id}`, {
    method: 'DELETE',
  }).then((r) => r.json() as Promise<{ id: number }>);
}

// ── Item functions (LIST-02) ────────────────────────────────────────────────

/**
 * Fetch all items for a list, ordered by rank ASC.
 * Returns active and completed items; the UI splits them into sections.
 */
export async function fetchListItems(listId: number): Promise<ListItemsResponse> {
  return apiFetch(`/lists/${listId}/items`).then((r) => r.json() as Promise<ListItemsResponse>);
}

/**
 * Add an item to a list. Server assigns the fractional rank (D-13).
 */
export async function addItem(listId: number, payload: { text: string }): Promise<ListItem> {
  return apiFetch(`/lists/${listId}/items`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload),
  }).then((r) => r.json() as Promise<ListItem>);
}

/**
 * Per-field PATCH for a list item (D-08).
 * Exactly one of: checked, text, or position.
 * Enforced server-side by zod refine; callers must pass exactly one field.
 */
export async function patchListItem(
  itemId: number,
  patch: { checked: boolean } | { text: string } | { position: string },
): Promise<ListItem> {
  return apiFetch(`/list-items/${itemId}`, {
    method: 'PATCH',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(patch),
  }).then((r) => r.json() as Promise<ListItem>);
}

/**
 * Delete an item instantly — no confirmation (D-06).
 * Delete-wins semantics (D-09): no rollback in the client after success.
 */
export async function deleteItem(itemId: number): Promise<{ id: number }> {
  return apiFetch(`/list-items/${itemId}`, {
    method: 'DELETE',
  }).then((r) => r.json() as Promise<{ id: number }>);
}
