{"version":3,"file":"sorting.cjs","sources":["../../../src/core/sorting.ts"],"sourcesContent":["/**\n * E-Commerce Custom Sorting System\n * Works with multi-field search results to sort by any field\n */\n\nimport type { SuggestionResult } from \"./types.js\";\n\n/**\n * Sort option for a field\n */\nexport interface SortOption {\n  field: string;\n  order: \"asc\" | \"desc\";\n  type?: \"number\" | \"string\" | \"date\";\n}\n\n/**\n * Sort configuration\n */\nexport interface SortConfig {\n  primary: SortOption;\n  secondary?: SortOption;\n  keepRelevance?: boolean;\n}\n\n/**\n * Apply custom sorting to search results\n * Works with result.fields property populated by multi-field search\n */\nexport function applySorting(results: SuggestionResult[], sortConfig: SortConfig): SuggestionResult[] {\n  const sorted = [...results];\n\n  sorted.sort((a, b) => {\n    // Primary sort\n    const primaryCompare = compareResults(a, b, sortConfig.primary);\n    if (primaryCompare !== 0) return primaryCompare;\n\n    // Secondary sort\n    if (sortConfig.secondary) {\n      const secondaryCompare = compareResults(a, b, sortConfig.secondary);\n      if (secondaryCompare !== 0) return secondaryCompare;\n    }\n\n    // Final tie-breaker: relevance score\n    if (sortConfig.keepRelevance !== false) {\n      return b.score - a.score;\n    }\n\n    return 0;\n  });\n\n  return sorted;\n}\n\nfunction compareResults(a: SuggestionResult, b: SuggestionResult, sort: SortOption): number {\n  const aValue = a.fields?.[sort.field];\n  const bValue = b.fields?.[sort.field];\n\n  if (aValue === undefined && bValue === undefined) return 0;\n  if (aValue === undefined) return 1;\n  if (bValue === undefined) return -1;\n\n  const type = sort.type || detectType(aValue);\n\n  let comparison = 0;\n\n  switch (type) {\n    case \"number\":\n      comparison = compareNumbers(aValue, bValue);\n      break;\n    case \"date\":\n      comparison = compareDates(aValue, bValue);\n      break;\n    case \"string\":\n    default:\n      comparison = compareStrings(aValue, bValue);\n  }\n\n  return sort.order === \"desc\" ? -comparison : comparison;\n}\n\nfunction compareNumbers(a: any, b: any): number {\n  const numA = Number(a);\n  const numB = Number(b);\n\n  if (isNaN(numA) && isNaN(numB)) return 0;\n  if (isNaN(numA)) return 1;\n  if (isNaN(numB)) return -1;\n\n  return numA - numB;\n}\n\nfunction compareDates(a: any, b: any): number {\n  const dateA = new Date(a);\n  const dateB = new Date(b);\n\n  const timeA = dateA.getTime();\n  const timeB = dateB.getTime();\n\n  if (isNaN(timeA) && isNaN(timeB)) return 0;\n  if (isNaN(timeA)) return 1;\n  if (isNaN(timeB)) return -1;\n\n  return timeA - timeB;\n}\n\nfunction compareStrings(a: any, b: any): number {\n  return String(a).localeCompare(String(b));\n}\n\nfunction detectType(value: any): \"number\" | \"string\" | \"date\" {\n  if (typeof value === \"number\") return \"number\";\n  \n  if (typeof value === \"string\" && !isNaN(parseFloat(value)) && isFinite(Number(value))) {\n    return \"number\";\n  }\n  \n  if (value instanceof Date) return \"date\";\n  \n  if (typeof value === \"string\") {\n    const date = new Date(value);\n    if (!isNaN(date.getTime()) && /\\d{4}-\\d{2}-\\d{2}|\\d{2}\\/\\d{2}\\/\\d{4}/.test(value)) {\n      return \"date\";\n    }\n  }\n  \n  return \"string\";\n}\n"],"names":[],"mappings":";;AA6BO,SAAS,aAAa,SAA6B,YAA4C;AACpG,QAAM,SAAS,CAAC,GAAG,OAAO;AAE1B,SAAO,KAAK,CAAC,GAAG,MAAM;AAEpB,UAAM,iBAAiB,eAAe,GAAG,GAAG,WAAW,OAAO;AAC9D,QAAI,mBAAmB,EAAG,QAAO;AAGjC,QAAI,WAAW,WAAW;AACxB,YAAM,mBAAmB,eAAe,GAAG,GAAG,WAAW,SAAS;AAClE,UAAI,qBAAqB,EAAG,QAAO;AAAA,IACrC;AAGA,QAAI,WAAW,kBAAkB,OAAO;AACtC,aAAO,EAAE,QAAQ,EAAE;AAAA,IACrB;AAEA,WAAO;AAAA,EACT,CAAC;AAED,SAAO;AACT;AAEA,SAAS,eAAe,GAAqB,GAAqB,MAA0B;AAC1F,QAAM,SAAS,EAAE,SAAS,KAAK,KAAK;AACpC,QAAM,SAAS,EAAE,SAAS,KAAK,KAAK;AAEpC,MAAI,WAAW,UAAa,WAAW,OAAW,QAAO;AACzD,MAAI,WAAW,OAAW,QAAO;AACjC,MAAI,WAAW,OAAW,QAAO;AAEjC,QAAM,OAAO,KAAK,QAAQ,WAAW,MAAM;AAE3C,MAAI,aAAa;AAEjB,UAAQ,MAAA;AAAA,IACN,KAAK;AACH,mBAAa,eAAe,QAAQ,MAAM;AAC1C;AAAA,IACF,KAAK;AACH,mBAAa,aAAa,QAAQ,MAAM;AACxC;AAAA,IACF,KAAK;AAAA,IACL;AACE,mBAAa,eAAe,QAAQ,MAAM;AAAA,EAAA;AAG9C,SAAO,KAAK,UAAU,SAAS,CAAC,aAAa;AAC/C;AAEA,SAAS,eAAe,GAAQ,GAAgB;AAC9C,QAAM,OAAO,OAAO,CAAC;AACrB,QAAM,OAAO,OAAO,CAAC;AAErB,MAAI,MAAM,IAAI,KAAK,MAAM,IAAI,EAAG,QAAO;AACvC,MAAI,MAAM,IAAI,EAAG,QAAO;AACxB,MAAI,MAAM,IAAI,EAAG,QAAO;AAExB,SAAO,OAAO;AAChB;AAEA,SAAS,aAAa,GAAQ,GAAgB;AAC5C,QAAM,QAAQ,IAAI,KAAK,CAAC;AACxB,QAAM,QAAQ,IAAI,KAAK,CAAC;AAExB,QAAM,QAAQ,MAAM,QAAA;AACpB,QAAM,QAAQ,MAAM,QAAA;AAEpB,MAAI,MAAM,KAAK,KAAK,MAAM,KAAK,EAAG,QAAO;AACzC,MAAI,MAAM,KAAK,EAAG,QAAO;AACzB,MAAI,MAAM,KAAK,EAAG,QAAO;AAEzB,SAAO,QAAQ;AACjB;AAEA,SAAS,eAAe,GAAQ,GAAgB;AAC9C,SAAO,OAAO,CAAC,EAAE,cAAc,OAAO,CAAC,CAAC;AAC1C;AAEA,SAAS,WAAW,OAA0C;AAC5D,MAAI,OAAO,UAAU,SAAU,QAAO;AAEtC,MAAI,OAAO,UAAU,YAAY,CAAC,MAAM,WAAW,KAAK,CAAC,KAAK,SAAS,OAAO,KAAK,CAAC,GAAG;AACrF,WAAO;AAAA,EACT;AAEA,MAAI,iBAAiB,KAAM,QAAO;AAElC,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,OAAO,IAAI,KAAK,KAAK;AAC3B,QAAI,CAAC,MAAM,KAAK,QAAA,CAAS,KAAK,wCAAwC,KAAK,KAAK,GAAG;AACjF,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;;"}