import { supabase, hasSupabaseConfig, } from "../supabaseClient"; const SHOWCASE_TOKEN = "showcase"; const LOCAL_CLIENT_FLOW_TOKEN_PREFIX = "client-flow-"; const LOCAL_CLIENT_FLOW_TOKEN = "client-flow-1001"; const LOCAL_INVITATION_STORAGE_PREFIX = "delivery-invitation:"; const localDeliveryInvitationCache = new Map(); const formatIsoDate = (date) => date.toISOString().slice(0, 10); const addDays = (date, days) => { const next = new Date(date); next.setUTCDate(next.getUTCDate() + days); return next; }; const cloneInvitation = (invitation) => JSON.parse(JSON.stringify(invitation)); const getLocalStorage = () => { try { return globalThis.localStorage || null; } catch { return null; } }; const getLocalStorageKey = (token) => `${LOCAL_INVITATION_STORAGE_PREFIX}${token}`; const readStoredInvitation = (token) => { const storage = getLocalStorage(); if (!storage) { return null; } try { const raw = storage.getItem(getLocalStorageKey(token)); return raw ? JSON.parse(raw) : null; } catch { return null; } }; const writeStoredInvitation = (invitation) => { const storage = getLocalStorage(); if (!storage?.setItem) { return; } try { storage.setItem(getLocalStorageKey(invitation.token), JSON.stringify(invitation)); } catch { // Ignore storage quota and privacy mode failures. } }; const isLocalClientInvitationToken = (token) => token === SHOWCASE_TOKEN || token?.startsWith(LOCAL_CLIENT_FLOW_TOKEN_PREFIX); const buildLocalClientInvitation = (token = LOCAL_CLIENT_FLOW_TOKEN, now = new Date()) => { const firstDay = formatIsoDate(addDays(now, 1)); const secondDay = formatIsoDate(addDays(now, 2)); return { token, orderId: "order-cd-240031", orderNumber: "CD-240031", customerName: "Мария Волкова", customerPhone: "+7 978 000-12-31", state: "awaiting_choice", deliveryDate: firstDay, deliveryTime: "До обеда", orderItems: [ { name: "Кухонный гарнитур", quantity: "1 комплект" }, { name: "Фурнитура Blum", quantity: "12 шт" }, { name: "Монтажный комплект", quantity: "1 набор" }, ], availableSlots: [ `${firstDay}, До обеда`, `${firstDay}, После обеда`, `${secondDay}, До обеда`, `${secondDay}, После обеда`, ], }; }; const getCachedInvitation = (token) => { const invitation = localDeliveryInvitationCache.get(token); return invitation ? cloneInvitation(invitation) : null; }; const cacheInvitation = (invitation) => { const clonedInvitation = cloneInvitation(invitation); localDeliveryInvitationCache.set(clonedInvitation.token, clonedInvitation); if (isLocalClientInvitationToken(clonedInvitation.token)) { writeStoredInvitation(clonedInvitation); } return getCachedInvitation(clonedInvitation.token); }; const buildFallbackInvitation = (token) => token === SHOWCASE_TOKEN ? buildShowcaseInvitation(token) : buildLocalClientInvitation(token); const warmLocalInvitationCache = (token, functionName) => { void invokeDeliveryFunction(functionName, { token }) .then((response) => { if (response?.invitation) { cacheInvitation(response.invitation); } }) .catch(() => undefined); }; export const buildShowcaseInvitation = (token = SHOWCASE_TOKEN, now = new Date()) => { const firstDay = formatIsoDate(addDays(now, 1)); const secondDay = formatIsoDate(addDays(now, 2)); return { token, orderId: "showcase-order", orderNumber: "CD-CLIENT-001", customerName: "Мария Волкова", customerPhone: "+7 978 000-12-31", state: "awaiting_choice", deliveryDate: firstDay, deliveryTime: "До обеда", orderItems: [ { name: "Кухонный гарнитур", quantity: "1 комплект" }, { name: "Фурнитура Blum", quantity: "12 шт" }, { name: "Монтажный комплект", quantity: "1 набор" }, ], availableSlots: [ `${firstDay}, До обеда`, `${firstDay}, После обеда`, `${secondDay}, До обеда`, `${secondDay}, После обеда`, ], }; }; const invokeDeliveryFunction = async (functionName, body) => { if (!hasSupabaseConfig || !supabase?.functions?.invoke) { throw new Error("Supabase is not configured"); } const { data, error } = await supabase.functions.invoke(functionName, { body, }); if (error) { throw error; } return data; }; const callDeliveryRpc = async (functionName, params) => { if (!hasSupabaseConfig || !supabase?.rpc) { throw new Error("Supabase is not configured"); } const { data, error } = await supabase.rpc(functionName, params); if (error) { throw error; } if (data && data.ok === false) { throw new Error(data.error || "Request failed"); } return data; }; export const __resetLocalDeliveryInvitationCache = () => { localDeliveryInvitationCache.clear(); }; export const fetchDeliveryInvitation = async (token) => { if (!token) { throw new Error("Token is required"); } if (isLocalClientInvitationToken(token)) { const cachedInvitation = getCachedInvitation(token); const storedInvitation = cachedInvitation ?? readStoredInvitation(token); const invitation = storedInvitation ? cacheInvitation(storedInvitation) : cacheInvitation(buildFallbackInvitation(token)); warmLocalInvitationCache(token, "get-delivery-invitation"); return invitation; } const cachedInvitation = getCachedInvitation(token); if (cachedInvitation) { return cachedInvitation; } try { const response = await callDeliveryRpc("get_delivery_invitation_by_token", { p_token: token, }); if (response?.invitation) { return cacheInvitation(response.invitation); } if (isLocalClientInvitationToken(token)) { return cacheInvitation(buildFallbackInvitation(token)); } return response?.invitation; } catch (error) { if (isLocalClientInvitationToken(token)) { return cacheInvitation(buildFallbackInvitation(token)); } throw error; } }; export const confirmDeliveryChoice = async ({ token, deliveryDate, deliveryTime, deliveryType, pickupDate, pickupTimeSlot, deliveryAddress }) => { if (isLocalClientInvitationToken(token)) { const baseInvitation = getCachedInvitation(token) ?? buildFallbackInvitation(token); const invitation = cacheInvitation({ ...baseInvitation, deliveryType: deliveryType || "delivery", ...(deliveryType === "pickup" ? { pickupDate, pickupTimeSlot } : {}), ...(deliveryType === "delivery" && deliveryAddress ? { deliveryAddress, customerAddress: deliveryAddress } : {}), deliveryDate, deliveryTime, state: "confirmed", }); warmLocalInvitationCache(token, "confirm-delivery-choice"); return { ok: true, invitation }; } return callDeliveryRpc("confirm_delivery_choice_by_token", { p_token: token, p_delivery_date: deliveryDate, p_delivery_time: deliveryTime, p_delivery_type: deliveryType || "delivery", p_pickup_date: pickupDate || null, p_pickup_time_slot: pickupTimeSlot || null, p_delivery_address: deliveryAddress || null, }); }; export const requestDeliveryLink = async ({ orderId, orderGroupId, orderNumber, customerName, customerPhone, customerMessenger, availableSlots, }) => invokeDeliveryFunction("create-delivery-invitation", { orderId, orderGroupId, orderNumber, customerName, customerPhone, customerMessenger, availableSlots, }); export const transferDeliveryToLogistics = async ({ orderId, reason, note, targetStatus }) => invokeDeliveryFunction("transfer-to-logistics", { orderId, reason, note, targetStatus, }); export const reportDeliveryResult = async ({ orderId, result, note, payload }) => invokeDeliveryFunction("report-delivery-result", { orderId, result, note, payload, });