import { useCallback, useEffect, useRef, useState } from 'react' import { toast } from '@/components/ui/toast' export interface QuantitySelectorDefaults { display: 'input' | 'dropdown' | 'buttons' choice_source: 'range' | 'custom' choices: string suffix: string width: number } const defaults: QuantitySelectorDefaults = { display: 'input', choice_source: 'range', choices: '', suffix: '', width: 100 } const endpoint = () => `${(window.swiftCommerceData?.apiUrl || '/wp-json/swift-commerce/v1').replace(/\/$/, '')}/quantity-limits/selector-defaults` export function parseSelectorDefaults(value: unknown): QuantitySelectorDefaults { const settings = value as QuantitySelectorDefaults | null if (!settings || !['input', 'dropdown', 'buttons'].includes(settings.display) || !['range', 'custom'].includes(settings.choice_source) || !Number.isInteger(settings.width) || settings.width < 80 || settings.width > 320 || typeof settings.choices !== 'string' || typeof settings.suffix !== 'string') throw new Error('Product defaults could not be read.') return {display: settings.display, choice_source: settings.choice_source, choices: settings.choices, suffix: settings.suffix, width: settings.width} } /** Pro-owned endpoint; a failed load never supplies writable fallback settings. */ export function useSelectorDefaults(enabled: boolean) { const [settings, setSettings] = useState(null) const [initial, setInitial] = useState(null) const [loading, setLoading] = useState(enabled) const [saving, setSaving] = useState(false) const [error, setError] = useState(null) const [attempt, setAttempt] = useState(0) const saveLock = useRef(false) useEffect(() => { if (!enabled) { setSettings(null); setInitial(null); setLoading(false); return } const controller = new AbortController() setLoading(true); setError(null) fetch(endpoint(), {signal: controller.signal, headers: {'X-WP-Nonce': window.swiftCommerceData?.restNonce || ''}}) .then(async response => { if (!response.ok) throw new Error('Could not load product defaults.'); return response.json() }) .then(data => { const value = parseSelectorDefaults(data.settings) if (!controller.signal.aborted) { setSettings(value); setInitial(value) } }) .catch(() => { if (!controller.signal.aborted) { setSettings(null); setInitial(null); setError('Product defaults could not be loaded. Please try again.') } }) .finally(() => { if (!controller.signal.aborted) setLoading(false) }) return () => controller.abort() }, [enabled, attempt]) const save = async () => { if (!enabled || loading || saveLock.current || !settings || !initial || error) return false saveLock.current = true const submitted = settings setSaving(true) try { const response = await fetch(endpoint(), {method: 'POST', headers: {'Content-Type': 'application/json', 'X-WP-Nonce': window.swiftCommerceData?.restNonce || ''}, body: JSON.stringify({settings})}) const data = await response.json() if (!response.ok || !data.success) throw new Error(data.message || 'Could not save product defaults.') const saved = parseSelectorDefaults(data.settings) setSettings(current => JSON.stringify(current) === JSON.stringify(submitted) ? saved : current) setInitial(saved) return true } catch (reason) { toast.error(reason instanceof Error ? reason.message : 'Could not save product defaults.'); return false } finally { saveLock.current = false; setSaving(false) } } return {settings, setSettings, loading, saving, error, save, hasChanges: !!settings && !!initial && JSON.stringify(settings) !== JSON.stringify(initial), retry: useCallback(() => setAttempt(value => value + 1), []), reset: () => { if (initial) setSettings({...defaults}) }} }