{
  "version": 3,
  "sources": ["../../../src/functions/criteria-parser.ts"],
  "sourcesContent": [
    "import { FormulaError, type CellValue } from \"../core/types.mjs\";\n\n/**\n * Parsed criteria result\n */\nexport type ParsedCriteria = \n  | { type: \"exact\"; value: CellValue }\n  | { type: \"comparison\"; operator: \">\" | \"<\" | \">=\" | \"<=\" | \"<>\"; value: CellValue }\n  | { type: \"wildcard\"; pattern: string }\n  | { type: \"error\"; message: string };\n\n/**\n * Convert wildcard pattern to regex\n */\nfunction wildcardToRegex(pattern: string): RegExp {\n  // Escape regex special characters except * and ?\n  const escaped = pattern.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\");\n  // Convert wildcards: * -> .*, ? -> .\n  const regexPattern = escaped.replace(/\\*/g, \".*\").replace(/\\?/g, \".\");\n  return new RegExp(`^${regexPattern}$`);\n}\n\n/**\n * Parse a simple value string to determine its type\n * This is a lightweight alternative to parseFormula for criteria strings\n */\nfunction parseSimpleValue(valueStr: string): CellValue {\n  // Trim the value\n  const trimmed = valueStr.trim();\n  \n  // Check for boolean values (case-insensitive)\n  const upperTrimmed = trimmed.toUpperCase();\n  if (upperTrimmed === \"TRUE\") {\n    return { type: \"boolean\", value: true };\n  }\n  if (upperTrimmed === \"FALSE\") {\n    return { type: \"boolean\", value: false };\n  }\n  \n  // Check for infinity values (case-insensitive)\n  if (upperTrimmed === \"INFINITY\") {\n    return { type: \"infinity\", sign: \"positive\" };\n  }\n  if (upperTrimmed === \"-INFINITY\") {\n    return { type: \"infinity\", sign: \"negative\" };\n  }\n  \n  // Check for numeric values\n  // Match: optional negative sign, digits, optional decimal point and more digits\n  // Examples: \"10\", \"-20\", \"3.14\", \"-0.5\", \"0\"\n  if (/^-?\\d+(\\.\\d+)?$/.test(trimmed)) {\n    const num = Number(trimmed);\n    if (!isNaN(num) && isFinite(num)) {\n      return { type: \"number\", value: num };\n    }\n  }\n  \n  // Default to string\n  return { type: \"string\", value: valueStr };\n}\n\n/**\n * Simple criteria parser for COUNTIF\n * Handles: exact values, comparisons (>5, <=10, <>0), and wildcards (*app, ?at)\n */\nexport function parseCriteria(criteria: CellValue): ParsedCriteria {\n  // Only string criteria can contain operators or wildcards\n  if (criteria.type !== \"string\") {\n    return { type: \"exact\", value: criteria };\n  }\n\n  const criteriaStr = criteria.value;\n\n  // Handle empty string as exact match\n  if (criteriaStr === \"\") {\n    return { type: \"exact\", value: criteria };\n  }\n\n  // Special case: \"=\" means count empty cells\n  if (criteriaStr === \"=\") {\n    return { type: \"exact\", value: { type: \"string\", value: \"\" } };\n  }\n\n  // Check for comparison operators (must be at the beginning)\n  const comparisonMatch = criteriaStr.match(/^(>=|<=|<>|>|<)(.*)$/);\n  if (comparisonMatch) {\n    const operator = comparisonMatch[1];\n    const valueStr = comparisonMatch[2];\n    \n    if (!operator || valueStr === undefined) {\n      return { type: \"error\", message: \"Invalid comparison operator format\" };\n    }\n    \n    // Special case: \"<>\" with no value means \"not empty\"\n    if (operator === \"<>\" && valueStr === \"\") {\n      return { \n        type: \"comparison\", \n        operator: \"<>\", \n        value: { type: \"string\", value: \"\" } \n      };\n    }\n\n    // Parse the value part to get the proper type\n    const parsedValue = parseSimpleValue(valueStr);\n    return { \n      type: \"comparison\", \n      operator: operator as \">\" | \"<\" | \">=\" | \"<=\" | \"<>\", \n      value: parsedValue\n    };\n  }\n\n  // Check for wildcards\n  if (criteriaStr.includes(\"*\") || criteriaStr.includes(\"?\")) {\n    return { type: \"wildcard\", pattern: criteriaStr };\n  }\n\n  // Parse as a simple value to get the proper type\n  const parsedValue = parseSimpleValue(criteriaStr);\n  return { type: \"exact\", value: parsedValue };\n}\n\n/**\n * Check if a cell value matches the parsed criteria\n */\nexport function matchesParsedCriteria(cellValue: CellValue, parsedCriteria: ParsedCriteria): boolean {\n  switch (parsedCriteria.type) {\n    case \"error\":\n      return false;\n\n    case \"exact\":\n      // Exact match - must be same type and value\n      if (cellValue.type !== parsedCriteria.value.type) {\n        return false;\n      }\n      if (\"value\" in cellValue && \"value\" in parsedCriteria.value) {\n        if (cellValue.type === 'string' && parsedCriteria.value.type === 'string') {\n          return cellValue.value.toLowerCase() === parsedCriteria.value.value.toLowerCase();\n        }\n        return cellValue.value === parsedCriteria.value.value;\n      }\n      if (cellValue.type === \"infinity\" && parsedCriteria.value.type === \"infinity\") {\n        return cellValue.sign === parsedCriteria.value.sign;\n      }\n      return false;\n\n    case \"comparison\":\n      // Special case: \"<>\" with empty string means \"not empty\"\n      if (parsedCriteria.operator === \"<>\" && \n          parsedCriteria.value.type === \"string\" && \n          parsedCriteria.value.value === \"\") {\n        return cellValue.type !== \"string\" || cellValue.value !== \"\";\n      }\n\n      // For other comparisons, handle by operator\n      if (parsedCriteria.operator === \"<>\") {\n        // Not equals - same logic as exact but negated\n        if (cellValue.type !== parsedCriteria.value.type) {\n          return true; // Different types are not equal\n        }\n        if (\"value\" in cellValue && \"value\" in parsedCriteria.value) {\n          return cellValue.value !== parsedCriteria.value.value;\n        }\n        if (cellValue.type === \"infinity\" && parsedCriteria.value.type === \"infinity\") {\n          return cellValue.sign !== parsedCriteria.value.sign;\n        }\n        return true;\n      }\n\n      // Numeric comparison operators - only work with numbers and infinity\n      if (cellValue.type !== \"number\" && cellValue.type !== \"infinity\") {\n        return false;\n      }\n      if (parsedCriteria.value.type !== \"number\" && parsedCriteria.value.type !== \"infinity\") {\n        return false; // Can only compare with numeric or infinity criteria\n      }\n\n      // Handle when criteria is infinity\n      if (parsedCriteria.value.type === \"infinity\") {\n        const criteriaSign = parsedCriteria.value.sign;\n        \n        // Handle when cell value is also infinity\n        if (cellValue.type === \"infinity\") {\n          const cellSign = cellValue.sign;\n          switch (parsedCriteria.operator) {\n            case \">\":\n              // +∞ > -∞, but not +∞ > +∞\n              return cellSign === \"positive\" && criteriaSign === \"negative\";\n            case \"<\":\n              // -∞ < +∞, but not -∞ < -∞\n              return cellSign === \"negative\" && criteriaSign === \"positive\";\n            case \">=\":\n              // +∞ >= +∞, +∞ >= -∞, but not -∞ >= +∞\n              return cellSign === \"positive\" || (cellSign === criteriaSign);\n            case \"<=\":\n              // -∞ <= -∞, -∞ <= +∞, but not +∞ <= -∞\n              return cellSign === \"negative\" || (cellSign === criteriaSign);\n            default:\n              return false;\n          }\n        }\n        \n        // Handle when cell value is a finite number\n        if (cellValue.type === \"number\") {\n          switch (parsedCriteria.operator) {\n            case \">\":\n              // No finite number is > +∞, all finite numbers > -∞\n              return criteriaSign === \"negative\";\n            case \"<\":\n              // All finite numbers < +∞, no finite number < -∞\n              return criteriaSign === \"positive\";\n            case \">=\":\n              // No finite number >= +∞, all finite numbers >= -∞\n              return criteriaSign === \"negative\";\n            case \"<=\":\n              // All finite numbers <= +∞, no finite number <= -∞\n              return criteriaSign === \"positive\";\n            default:\n              return false;\n          }\n        }\n      }\n\n      // Handle when criteria is a number (not infinity)\n      if (parsedCriteria.value.type === \"number\") {\n        const criteriaNum = parsedCriteria.value.value;\n\n        // Handle infinity cell values with numeric criteria\n        if (cellValue.type === \"infinity\") {\n          switch (parsedCriteria.operator) {\n            case \">\":\n              return cellValue.sign === \"positive\"; // +∞ > any number\n            case \"<\":\n              return cellValue.sign === \"negative\"; // -∞ < any number\n            case \">=\":\n              return cellValue.sign === \"positive\"; // +∞ >= any number\n            case \"<=\":\n              return cellValue.sign === \"negative\"; // -∞ <= any number\n            default:\n              return false;\n          }\n        }\n\n        // Regular number comparison\n        if (cellValue.type === \"number\") {\n          switch (parsedCriteria.operator) {\n            case \">\":\n              return cellValue.value > criteriaNum;\n            case \"<\":\n              return cellValue.value < criteriaNum;\n            case \">=\":\n              return cellValue.value >= criteriaNum;\n            case \"<=\":\n              return cellValue.value <= criteriaNum;\n            default:\n              return false;\n          }\n        }\n      }\n      \n      return false;\n\n    case \"wildcard\":\n      // Wildcard matching - only works with strings\n      if (cellValue.type !== \"string\") {\n        return false;\n      }\n      const regex = wildcardToRegex(parsedCriteria.pattern);\n      return regex.test(cellValue.value);\n\n    default:\n      return false;\n  }\n}\n"
  ],
  "mappings": "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",
  "debugId": "3124178E3660C7AD64756E2164756E21",
  "names": []
}