import api from './api'; import { PRODUCTS, Product, PetType } from "../data/products"; const CATEGORY_SLUG_TO_NAME: Record = { 'joints': 'مفاصل و استخوان', 'immune': 'تقویت سیستم ایمنی و گوارش', 'energy': 'ویتامین‌ها و انرژی‌بخش‌ها', 'special-care': 'مراقبت‌های ویژه (پوست، دندان و چشم)', 'general': 'تقویت عمومی', 'nutrition': 'تغذیه تخصصی', 'supplements': 'مکمل‌های غذایی و درمانی', }; export class ProductService { private static instance: ProductService; private constructor() {} public static getInstance(): ProductService { if (!ProductService.instance) { ProductService.instance = new ProductService(); } return ProductService.instance; } private mapBackendToFrontend(inputData: Record): Product { const data = inputData as any; // Find the local static product to inherit functions like calculateDosage const local = PRODUCTS.find(p => p.artNo === data.artNo || p.id === data.productGroup || (typeof data.slug === 'string' && data.slug.includes(p.id)) ); const safeParse = (val: unknown, fallback: unknown) => { if (!val) return fallback; if (typeof val === 'string') { try { return JSON.parse(val); } catch { return fallback; } } return val; }; return { id: data.id, artNo: data.artNo, name: data.nameFa || data.name || '', nameFa: data.nameFa || data.name || '', nameEn: data.nameEn || '', scientificTagline: data.scientificTagline, description: data.description, shortDescription: data.shortDescription || '', price: data.priceDisplay || `${data.priceValue.toLocaleString('fa-IR')} تومان`, priceValue: Number(data.priceValue), category: data.category?.name || data.category || CATEGORY_SLUG_TO_NAME[data.categorySlug] || data.categorySlug || '', categorySlug: data.categorySlug, unit: data.unit, packageSize: data.packageSize, dosage_logic: data.dosageLogic, benefits: data.benefits, suitableFor: data.suitableFor as PetType, requiresRx: Boolean(data.requiresRx), storage: data.storage, specialBadge: data.specialBadge, onSetOfAction: data.onSetOfAction, optimisticTemplate: data.optimisticTemplate, feedingAdvice: data.dosageLogic || data.feedingAdvice || '', slug: data.slug, image: (data.imageUrl && data.imageUrl.startsWith('http')) ? data.imageUrl : (local?.image || (data.imageUrl ? `/api${data.imageUrl}` : data.image || '')), main_ingredients: data.ingredientList?.map((i: { ingredient: string }) => i.ingredient) || data.ingredients?.split(/[،,-]/).map((s: string) => s.trim()).filter(Boolean) || [], symptoms: data.symptoms?.map((s: { symptom?: string }) => s.symptom || s) || [], keyBenefits: safeParse(data.keyBenefits, []), expectedResults: safeParse(data.expectedResults, []), benefitsList: safeParse(data.benefitsList, []), faqs: safeParse(data.faqs, []), analysis: safeParse(data.analysis, {}), specialist: safeParse(data.specialist, null), relatedProducts: safeParse(data.relatedProducts, []), contraindications: safeParse(data.contraindications, []), calculateDosage: local?.calculateDosage || (() => ({ quantity: 0, unit: '', description: '' })) }; } public async getProducts(filters?: { category?: string; petType?: PetType | "all"; query?: string; symptom?: string; page?: number; limit?: number; }): Promise<{ data: Product[]; meta: { total: number; page: number; lastPage: number; limit: number } }> { const params = new URLSearchParams(); if (filters?.category && filters.category !== "all") params.append('category', filters.category); if (filters?.petType && filters.petType !== "all") params.append('petType', filters.petType); if (filters?.query) params.append('search', filters.query); if (filters?.symptom) params.append('symptom', filters.symptom); params.append('page', String(filters?.page || 1)); params.append('limit', String(filters?.limit || 12)); try { const response = await api.get(`/products?${params.toString()}`); return { data: response.data.data.map((item: Record) => this.mapBackendToFrontend(item)), meta: response.data.meta, }; } catch (error) { console.error("[ProductService] Failed to fetch products:", error); return { data: [], meta: { total: 0, page: 1, lastPage: 0, limit: 12 } }; } } public async getProductById(id: string): Promise { try { const response = await api.get(`/products/${id}`); return this.mapBackendToFrontend(response.data); } catch (error) { console.error(`[ProductService] Failed to fetch product ${id}:`, error); return null; } } public async getProductBySlug(slug: string): Promise { try { const response = await api.get(`/products/${slug}`); return this.mapBackendToFrontend(response.data); } catch (error) { console.error(`[ProductService] Failed to fetch product ${slug}:`, error); return null; } } public async getFeaturedProducts(): Promise { try { const response = await api.get('/products?limit=30'); const all = response.data.data.map((item: Record) => this.mapBackendToFrontend(item)); const featured: Product[] = []; const categoriesSeen = new Set(); for (const p of all) { if (p.category && !categoriesSeen.has(p.category)) { featured.push(p); categoriesSeen.add(p.category); } if (featured.length === 4) break; } if (featured.length < 4) { for (const p of all) { if (!featured.some(f => f.id === p.id)) { featured.push(p); } if (featured.length === 4) break; } } return featured; } catch (error) { console.error("[ProductService] Failed to fetch featured products:", error); return []; } } public async getActiveFilters(): Promise<{ categories: { id: string; name: string; slug: string }[]; symptoms: string[]; petTypes: string[]; }> { try { const response = await api.get('/products/filters'); return response.data; } catch (error) { console.error("[ProductService] Failed to fetch active filters:", error); return { categories: [], symptoms: [], petTypes: [] }; } } public async getNavigationFilters(): Promise<{ id: string; name: string; slug: string; symptoms: string[]; }[]> { try { const response = await api.get('/products/navigation-filters'); return response.data; } catch (error) { console.error("[ProductService] Failed to fetch navigation filters:", error); return []; } } } export const productService = ProductService.getInstance();