import { fetchJson } from './apiClient'; import { getDeviceId } from '../lib/device'; export type GuestAiStyle = { id: number; key: string; name: string; category?: string | null; description?: string | null; provider?: string | null; provider_model?: string | null; requires_source_image?: boolean; is_premium?: boolean; metadata?: Record; }; export type GuestAiStylesMeta = { required_feature?: string | null; addon_keys?: string[] | null; allow_custom_prompt?: boolean; allowed_style_keys?: string[] | null; policy_message?: string | null; }; export type GuestAiEditOutput = { id: number; storage_disk?: string | null; storage_path?: string | null; provider_url?: string | null; url?: string | null; mime_type?: string | null; width?: number | null; height?: number | null; is_primary?: boolean; safety_state?: string | null; safety_reasons?: string[]; generated_at?: string | null; }; export type GuestAiEditRequest = { id: number; event_id: number; photo_id: number; style?: { id: number; key: string; name: string; } | null; provider?: string | null; provider_model?: string | null; status: 'queued' | 'processing' | 'succeeded' | 'failed' | 'blocked' | 'canceled' | string; safety_state?: string | null; safety_reasons?: string[]; failure_code?: string | null; failure_message?: string | null; queued_at?: string | null; started_at?: string | null; completed_at?: string | null; outputs: GuestAiEditOutput[]; }; export type GuestAiStylesResponse = { data: GuestAiStyle[]; meta: GuestAiStylesMeta; }; export type GuestAiEditEnvelope = { message?: string; duplicate?: boolean; data: GuestAiEditRequest; }; function deviceHeaders(): Record { return { 'X-Device-Id': getDeviceId(), }; } export async function fetchGuestAiStyles(eventToken: string): Promise { const response = await fetchJson( `/api/v1/events/${encodeURIComponent(eventToken)}/ai-styles`, { headers: deviceHeaders(), noStore: true, } ); const payload = response.data; return { data: Array.isArray(payload?.data) ? payload.data : [], meta: payload?.meta && typeof payload.meta === 'object' ? payload.meta : {}, }; } export async function createGuestAiEdit( eventToken: string, photoId: number, payload: { style_key?: string; prompt?: string; negative_prompt?: string; provider_model?: string; idempotency_key?: string; session_id?: string; metadata?: Record; } ): Promise { const response = await fetchJson( `/api/v1/events/${encodeURIComponent(eventToken)}/photos/${photoId}/ai-edits`, { method: 'POST', headers: { ...deviceHeaders(), 'Content-Type': 'application/json', }, body: JSON.stringify(payload), noStore: true, } ); if (!response.data || typeof response.data !== 'object' || !response.data.data) { throw new Error('AI edit request response is invalid.'); } return response.data; } export async function fetchGuestAiEditStatus(eventToken: string, requestId: number): Promise<{ data: GuestAiEditRequest }> { const response = await fetchJson<{ data: GuestAiEditRequest }>( `/api/v1/events/${encodeURIComponent(eventToken)}/ai-edits/${requestId}`, { headers: deviceHeaders(), noStore: true, } ); if (!response.data || typeof response.data !== 'object' || !response.data.data) { throw new Error('AI edit status response is invalid.'); } return response.data; }