import { getAccessToken, clearTokens, setTokens } from '../lib/api' import { getActiveBusinessId } from '../lib/businessContext' import { API_BASE_URL } from '../lib/config' import { ensureJpegUploadFile, ensureUploadFile } from '../utils/imageUpload' export interface MediaItem { id: string publicUrl: string fileName: string originalFileName: string mimeType: string width: number | null height: number | null } function isDataUrl(value: string) { return value.startsWith('data:') } function businessPath(suffix = '') { const businessId = getActiveBusinessId() if (!businessId) { throw new Error('No active business selected. Please sign in again.') } return `/businesses/${businessId}/media${suffix}` } async function refreshAccessToken() { const refreshToken = localStorage.getItem('meshkee_business_refresh_token') if (!refreshToken) return false const response = await fetch(`${API_BASE_URL}/auth/refresh`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ refreshToken }), }) if (!response.ok) { clearTokens() return false } const data = await response.json() setTokens(data.accessToken, data.refreshToken) return true } function parseUploadError(payload: unknown, status: number) { if (payload && typeof payload === 'object') { const message = (payload as { message?: string | string[] }).message if (Array.isArray(message)) { return message.join(', ') } if (typeof message === 'string' && message) { return message } } return `Upload failed with status ${status}` } export async function uploadMediaFiles( files: File[], signal?: AbortSignal, ): Promise { if (!files.length) return [] const send = async () => { const formData = new FormData() files.forEach((file) => formData.append('files', file)) const headers = new Headers() const accessToken = getAccessToken() if (accessToken) { headers.set('Authorization', `Bearer ${accessToken}`) } return fetch(`${API_BASE_URL}${businessPath()}`, { method: 'POST', headers, body: formData, signal, }) } let response = await send() if (response.status === 401) { const refreshed = await refreshAccessToken() if (refreshed) { response = await send() } } const payload = await response.json().catch(() => null) if (!response.ok) { throw new Error(parseUploadError(payload, response.status)) } return (payload.items as Array>).map((item) => ({ id: String(item.id), publicUrl: String(item.publicUrl), fileName: String(item.fileName), originalFileName: String(item.originalFileName), mimeType: String(item.mimeType), width: typeof item.width === 'number' ? item.width : null, height: typeof item.height === 'number' ? item.height : null, })) } export async function resolveDataUrlToMediaId( value: string | null, filename: string, existingMediaId?: string | null, ): Promise { if (!value) return null if (!isDataUrl(value)) { return existingMediaId ?? null } const file = filename.toLowerCase().endsWith('.png') ? await ensureUploadFile(value, filename) : await ensureJpegUploadFile(value, filename) const uploaded = await uploadMediaFiles([file]) return uploaded[0]?.id ?? null } export async function resolveHtmlEmbeddedDataUrls(html: string): Promise { if (!html.includes('data:')) return html const parser = new DOMParser() const doc = parser.parseFromString(html, 'text/html') const images = Array.from(doc.querySelectorAll('img')) for (let index = 0; index < images.length; index += 1) { const src = images[index].getAttribute('src') if (!src || !isDataUrl(src)) continue const file = await ensureJpegUploadFile(src, `inline-image-${index + 1}.jpg`) const uploaded = await uploadMediaFiles([file]) if (uploaded[0]) { images[index].setAttribute('src', uploaded[0].publicUrl) } } return doc.body.innerHTML } export async function resolveDataUrlsToMediaIds( values: string[], existingMediaIds: string[], ): Promise { const resolved: string[] = [] for (let index = 0; index < values.length; index += 1) { const value = values[index] if (isDataUrl(value)) { const file = await ensureJpegUploadFile(value, `product-image-${index + 1}.jpg`) const uploaded = await uploadMediaFiles([file]) if (uploaded[0]) resolved.push(uploaded[0].id) } else if (existingMediaIds[index]) { resolved.push(existingMediaIds[index]) } } return resolved }