// frontend/lib/mail/api.ts — mailApi (accounts/folders/list/detail/extract/reply/send) import type { AccountFolder, Conversation, EmailDetail, EmailRow, ExtractAllResponse, ExtractKind, ExtractResponse, MailAccount, ReplyDraft, SendRequest, SendResponse, } from "@/lib/types"; const J = { "Content-Type": "application/json" }; async function ok(r: Response): Promise { if (!r.ok) { let msg = `${r.status} ${r.statusText}`; try { const j = await r.json(); if (j?.detail) msg = j.detail; } catch { /* 본문 없음 */ } throw new Error(msg); } return r.json() as Promise; } export const mailApi = { accounts: () => fetch("/api/mail/accounts", { cache: "no-store" }).then((r) => ok(r)), folders: () => fetch("/api/mail/folders", { cache: "no-store" }).then((r) => ok(r)), list: (account: string | null, folder: string, q?: string) => { const qs = new URLSearchParams(); if (account) qs.set("account", account); qs.set("folder", folder); if (q && q.trim()) qs.set("q", q.trim()); return fetch(`/api/mail?${qs}`, { cache: "no-store" }).then((r) => ok(r)); }, sent: (account: string | null) => { const qs = new URLSearchParams(); if (account) qs.set("account", account); const suffix = qs.toString() ? `?${qs}` : ""; return fetch(`/api/mail/sent${suffix}`, { cache: "no-store" }).then((r) => ok(r)); }, drafts: (account: string | null) => { const qs = new URLSearchParams(); if (account) qs.set("account", account); const suffix = qs.toString() ? `?${qs}` : ""; return fetch(`/api/mail/drafts${suffix}`, { cache: "no-store" }).then((r) => ok(r)); }, detail: (id: string) => fetch(`/api/mail/${id}`, { cache: "no-store" }).then((r) => ok(r)), extract: (id: string, kind: ExtractKind, index = 0) => fetch(`/api/mail/${id}/extract`, { method: "POST", headers: J, body: JSON.stringify({ kind, index }), }).then((r) => ok(r)), extractAll: (id: string) => fetch(`/api/mail/${id}/extract-all`, { method: "POST", headers: J, body: "{}" }).then((r) => ok(r), ), // 아리 비서: 안읽음 집중 메일 중 미분석분을 LLM 으로 배치 분석(점진). triageAnalyze: (limit = 6) => fetch(`/api/mail/triage/analyze?limit=${limit}`, { method: "POST", headers: J, body: "{}" }).then( (r) => ok<{ analyzed: number; remaining: number; errors: number }>(r), ), // 아리 정리 기준 시각(이 시각 이후 도착한 새 메일만 정리) + 새 메일 수(읽음 무관). triageBaseline: () => fetch("/api/mail/triage/baseline", { cache: "no-store" }).then((r) => ok<{ since: string; count: number }>(r), ), // 기준 시각을 지금으로 재설정 — 이후 새 메일부터 다시. triageBaselineReset: () => fetch("/api/mail/triage/baseline", { method: "POST", headers: J, body: "{}" }).then((r) => ok<{ since: string; count: number }>(r), ), replyDraft: (id: string, reply_index: number | null) => fetch(`/api/mail/${id}/reply-draft`, { method: "POST", headers: J, body: JSON.stringify({ reply_index }), }).then((r) => ok(r)), send: (body: SendRequest) => fetch("/api/mail/send", { method: "POST", headers: J, body: JSON.stringify(body) }).then((r) => ok(r), ), sync: () => fetch("/api/mail/sync", { method: "POST", headers: J, body: "{}" }).then((r) => ok<{ accounts: number; upserted: number }>(r), ), star: (id: string, starred: boolean) => fetch(`/api/mail/${id}/star`, { method: "PATCH", headers: J, body: JSON.stringify({ starred }), }).then((r) => ok(r)), setRead: (id: string, read: boolean) => fetch(`/api/mail/${id}/read`, { method: "PATCH", headers: J, body: JSON.stringify({ read }), }).then((r) => ok(r)), archive: (id: string) => fetch(`/api/mail/${id}/archive`, { method: "POST", headers: J, body: "{}" }).then((r) => ok(r), ), unarchive: (id: string) => fetch(`/api/mail/${id}/unarchive`, { method: "POST", headers: J, body: "{}" }).then((r) => ok(r), ), remove: (id: string) => fetch(`/api/mail/${id}`, { method: "DELETE" }).then((r) => ok<{ ok: boolean; id: string }>(r)), // 첨부 다운로드용 URL(브라우저가 직접 내려받음) attachmentUrl: (id: string, attId: string) => `/api/mail/${id}/attachments/${attId}`, thread: (id: string) => fetch(`/api/mail/${id}/thread`, { cache: "no-store" }).then((r) => ok(r)), labels: (id: string, add: string[], remove: string[]) => fetch(`/api/mail/${id}/labels`, { method: "PATCH", headers: J, body: JSON.stringify({ add, remove }), }).then((r) => ok(r)), bulk: (ids: string[], action: string) => fetch("/api/mail/bulk", { method: "POST", headers: J, body: JSON.stringify({ ids, action }), }).then((r) => ok<{ ok: boolean; count: number; action: string }>(r)), };