const BASE = '/api';

async function apiFetch<T>(path: string, init?: RequestInit): Promise<T> {
  const res = await fetch(`${BASE}${path}`, {
    headers: { 'Content-Type': 'application/json', ...init?.headers },
    ...init,
  });
  if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
  return res.json() as Promise<T>;
}

export type Address = { name: string | null; email: string | null };

export type Folder = {
  id: string;
  imap_path: string;
  display_name: string;
  special_use: string | null;
  unread_count: number;
  total_count: number;
  synced_at: string | null;
};

export type Thread = {
  id: string;
  subject: string;
  participants: Address[];
  message_count: number;
  unread_count: number;
  last_message_at: string;
  snippet: string | null;
  has_flagged: boolean;
  has_attachment: boolean;
};

export type MessageSummary = {
  id: string;
  folder_id: string;
  thread_id: string | null;
  from_addr: Address;
  to_addrs: Address[];
  cc_addrs: Address[];
  subject: string;
  date_sent: string;
  snippet: string;
  flags: { seen: boolean; flagged: boolean; answered: boolean; draft: boolean };
  attachments: Array<{ name: string; size: number; type: string }>;
};

export type MessageFull = MessageSummary & {
  body_text: string | null;
  body_html: string | null;
};

export type SyncRequest = {
  account_id: string;
  client_version: number;
  mutations: Mutation[];
};

export type Mutation = {
  id: string;
  op: 'flag' | 'move' | 'delete' | 'send' | 'draft_save' | 'draft_delete';
  target_id: string;
  payload: Record<string, unknown>;
};

export type SyncResponse = {
  applied: string[];
  rejected: Array<{ id: string; reason: string }>;
  server_version: number;
  changes: Array<{ type: 'message' | 'thread'; data: unknown }>;
};

export const api = {
  accounts: {
    list: () => apiFetch<{ accounts: Array<{ id: string; email: string }> }>('/accounts'),
  },
  folders: {
    list: (accountId: string) =>
      apiFetch<{ folders: Folder[] }>(`/accounts/${accountId}/folders`),
  },
  threads: {
    list: (folderId: string, params?: { limit?: number; before?: string }) => {
      const qs = new URLSearchParams();
      if (params?.limit) qs.set('limit', String(params.limit));
      if (params?.before) qs.set('before', params.before);
      return apiFetch<{ threads: Thread[]; next_cursor: string | null }>(
        `/folders/${folderId}/threads?${qs}`
      );
    },
  },
  messages: {
    inThread: (threadId: string) =>
      apiFetch<{ messages: MessageSummary[] }>(`/threads/${threadId}/messages`),
    get: (id: string) => apiFetch<MessageFull>(`/messages/${id}`),
  },
  search: (accountId: string, q: string) =>
    apiFetch<{ results: MessageSummary[] }>(`/search?account_id=${accountId}&q=${encodeURIComponent(q)}`),
  sync: (body: SyncRequest) =>
    apiFetch<SyncResponse>('/sync', { method: 'POST', body: JSON.stringify(body) }),
};
