import { allow, deny } from "@/lib/decision" import { toApiError, type ApiDecision } from "@/lib/errors" import type { Review } from "@/lib/types" import { httpJson } from "./http" type Paginated = { items: T[] | null meta: { total: number offset: number limit: number } } export type ListReviewsOptions = { offset?: number limit?: number } function withOffsetLimit(path: string, options?: ListReviewsOptions): string { const offset = options?.offset ?? 0 const limit = options?.limit ?? 100 const searchParams = new URLSearchParams({ offset: String(offset), limit: String(limit), }) return `${path}?${searchParams.toString()}` } function unwrapItems(value: unknown): T[] { if (Array.isArray(value)) return value as T[] if (typeof value !== "object" || value === null) { throw new Error("Invalid response") } if ("items" in value) { const envelope = value as { items?: unknown } if (Array.isArray(envelope.items)) return envelope.items as T[] if (envelope.items === null) return [] } throw new Error("Invalid response") } export async function listReviews(options?: ListReviewsOptions): Promise { const res = await httpJson | Review[]>( withOffsetLimit("/api/v1/reviews", options), { cache: "no-store", }, ) return unwrapItems(res) } export async function listReviewsByOrder(orderId: string): Promise { const res = await httpJson | Review[]>( `/api/v1/orders/${encodeURIComponent(orderId)}/reviews`, { cache: "no-store" }, ) return unwrapItems(res) } export async function listReviewsByTargetUser(userId: string): Promise { const res = await httpJson | Review[]>( `/api/v1/users/${encodeURIComponent(userId)}/reviews`, { cache: "no-store" }, ) return unwrapItems(res) } export async function submitReview(input: { orderId: string rating: number content?: string }): Promise { try { await httpJson(`/api/v1/orders/${encodeURIComponent(input.orderId)}/review`, { method: "POST", cache: "no-store", json: { rating: input.rating, content: input.content }, }) return allow() } catch (error) { if (error instanceof Error && error.message === "UNAUTHORIZED") { return deny(401, "请先登录") } const apiError = toApiError(error) return deny(apiError.code, apiError.msg) } }