import type { BusinessService, BusinessServiceClass } from '@/api/types'; import { formatDuration, formatPriceToman } from '@/utils/format'; export function activeServiceClasses(classes: BusinessServiceClass[]): BusinessServiceClass[] { return [...classes] .filter((item) => item.isActive) .sort((a, b) => a.sortOrder - b.sortOrder || a.title.localeCompare(b.title, 'fa')); } export function usesServiceClasses( classesEnabled: boolean, classes: BusinessServiceClass[], ): boolean { return classesEnabled && activeServiceClasses(classes).length > 0; } export function getClassPriceForService( service: BusinessService, classId: string, ) { return service.classPrices?.find( (item) => item.classId === classId && item.isActive, ); } export function serviceHasActiveClassPrices( service: BusinessService, classes: BusinessServiceClass[], ): boolean { const activeIds = new Set(activeServiceClasses(classes).map((item) => item.id)); return (service.classPrices ?? []).some( (item) => item.isActive && activeIds.has(item.classId), ); } export function isServiceBookable( service: BusinessService, classesEnabled: boolean, classes: BusinessServiceClass[], ): boolean { if (!service.isActive) return false; if (!usesServiceClasses(classesEnabled, classes)) return true; return serviceHasActiveClassPrices(service, classes); } export function servicePriceLabel( service: BusinessService, classesEnabled: boolean, classes: BusinessServiceClass[], ): string { if (!usesServiceClasses(classesEnabled, classes)) { return `${formatPriceToman(service.price)} تومان`; } const activeClasses = activeServiceClasses(classes); const prices = activeClasses .map((item) => getClassPriceForService(service, item.id)) .filter(Boolean) .map((item) => Number.parseFloat(item!.price)); if (!prices.length) return 'قیمت تعیین نشده'; const min = Math.min(...prices); const max = Math.max(...prices); if (min === max) { return `${formatPriceToman(String(min))} تومان`; } return `از ${formatPriceToman(String(min))} تومان`; } export function serviceDurationLabel( service: BusinessService, classesEnabled: boolean, classes: BusinessServiceClass[], classId?: string | null, ): string { if (classId) { const classPrice = getClassPriceForService(service, classId); return formatDuration( classPrice?.durationMinutes ?? service.durationMinutes, service.serviceTemplate?.defaultDurationMinutes, ); } if (!usesServiceClasses(classesEnabled, classes)) { return formatDuration( service.durationMinutes, service.serviceTemplate?.defaultDurationMinutes, ); } const activeClasses = activeServiceClasses(classes); const durations = activeClasses .map((item) => getClassPriceForService(service, item.id)) .filter(Boolean) .map((item) => item!.durationMinutes ?? service.durationMinutes ?? service.serviceTemplate?.defaultDurationMinutes, ) .filter((value): value is number => value != null && value > 0); if (!durations.length) { return formatDuration( service.durationMinutes, service.serviceTemplate?.defaultDurationMinutes, ); } const min = Math.min(...durations); const max = Math.max(...durations); if (min === max) return `${min} دقیقه`; return `${min}–${max} دقیقه`; } export function resolvedServicePrice( service: BusinessService, classId: string, ): string | null { const classPrice = getClassPriceForService(service, classId); return classPrice?.price ?? null; } export function resolveServiceDurationMinutes( service: BusinessService, classesEnabled: boolean, classes: BusinessServiceClass[], classId?: string | null, ): number { if (classId) { const classPrice = getClassPriceForService(service, classId); const fromClass = classPrice?.durationMinutes ?? service.durationMinutes ?? service.serviceTemplate?.defaultDurationMinutes; if (fromClass != null && fromClass > 0) return fromClass; } if (usesServiceClasses(classesEnabled, classes) && classId) { const classPrice = getClassPriceForService(service, classId); const value = classPrice?.durationMinutes ?? service.durationMinutes ?? service.serviceTemplate?.defaultDurationMinutes; if (value != null && value > 0) return value; } const fallback = service.durationMinutes ?? service.serviceTemplate?.defaultDurationMinutes; return fallback != null && fallback > 0 ? fallback : 30; } export function totalDurationForServices( services: BusinessService[], classesEnabled: boolean, classes: BusinessServiceClass[], classId?: string | null, ): number { return services.reduce( (sum, service) => sum + resolveServiceDurationMinutes(service, classesEnabled, classes, classId), 0, ); } export function totalPriceForServices( services: BusinessService[], classesEnabled: boolean, classes: BusinessServiceClass[], classId?: string | null, ): number | null { if (usesServiceClasses(classesEnabled, classes)) { if (!classId) return null; let total = 0; for (const service of services) { const price = resolvedServicePrice(service, classId); if (!price) return null; total += Number.parseFloat(price); } return total; } return services.reduce((sum, service) => sum + Number.parseFloat(service.price), 0); }