{"version":3,"sources":["../src/search-state-to-url-parser/seo-slug-generator/index.ts","../src/domain-data-display-enricher/index.ts","../src/json-schema-to-zod-generator/index.ts","../src/domain-data-filters/index.ts","../src/domain-data-transformers/index.ts","../src/search-state-to-url-parser/search-to-url-query-serializer/index.ts","../src/postgre-search-sql-builder/filter/helpers.ts","../src/postgre-search-sql-builder/filter/schema-adapter.ts","../src/postgre-search-sql-builder/filter/processors/geospatial-processor.ts","../src/postgre-search-sql-builder/filter/processors/basic-processor.ts","../src/postgre-search-sql-builder/filter/processors/array-processor.ts","../src/postgre-search-sql-builder/filter/filter-converter.ts","../src/postgre-search-sql-builder/filter/processors/index.ts","../src/postgre-search-sql-builder/filter/fulltext-converter.ts","../src/postgre-search-sql-builder/core/orchestrator.ts","../src/postgre-search-sql-builder/shared/helpers.ts","../src/postgre-search-sql-builder/builders/list/list-helpers.ts","../src/postgre-search-sql-builder/shared/sort-parser.ts","../src/postgre-search-sql-builder/shared/sql-params-converter.ts","../src/postgre-search-sql-builder/builders/list/list-builder.ts","../src/postgre-search-sql-builder/index.ts"],"names":["format","sortFields","generateSeoSlugWithOptions","isArrayField","result"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * SEO Slug Generator - Gerador de URLs amigáveis para SEO\n * \n * Sistema para gerar slugs SEO baseados em filtros de busca,\n * extraindo campos como tipo, operação, cidade, bairro, etc.\n * \n * EXEMPLO DE USO:\n * Input: { tipo: \"Casa\", operacao: \"Venda\", endereco: { cidade: \"Ponta Grossa\", bairro: \"Uvaranas\" } }\n * Output: \"casa-venda-uvaranas-ponta-grossa\"\n * \n * @module horizon-platform-toolkit/packages/seo-slug-generator\n */\n\n// ==========================================\n// 📋 INTERFACES E TIPOS\n// ==========================================\n\n/**\n * Opções para geração de slug SEO\n */\nexport interface SeoSlugOptions {\n  slugPrefix?: string;        // Prefixo para o slug (ex: \"imoveis\")\n  maxSlugLength?: number;     // Tamanho máximo do slug (padrão: 100)\n}\n\n// ==========================================\n// 🎯 CONFIGURAÇÃO DE CAMPOS SEO\n// ==========================================\n\n/**\n * Campos usados para gerar slug SEO\n * Mapeamento de tipos de campo para possíveis nomes nos filtros\n */\nconst SEO_FIELDS = {\n  tipo: ['tipo', 'type'],\n  subtipo: ['subtipo', 'subtype', 'tipo_imovel'],\n  operacao: ['operacao', 'operation', 'finalidade'],\n  cidade: ['cidade', 'city', 'endereco_cidade', 'endereco.cidade'],\n  bairro: ['bairro', 'neighborhood', 'endereco_bairro', 'endereco.bairro'],\n  estado: ['estado', 'state', 'endereco_estado', 'endereco.estado']\n} as const;\n\n// ==========================================\n// 🔧 FUNÇÕES DE NORMALIZAÇÃO\n// ==========================================\n\n/**\n * Normaliza texto para slug URL-safe\n * Remove acentos, caracteres especiais e cria formato slug\n */\nfunction slugify(text: string): string {\n  return text\n    .toString()\n    .toLowerCase()\n    .trim()\n    // Acentos portugueses\n    .replace(/[àáâãäå]/g, 'a')\n    .replace(/[èéêë]/g, 'e')\n    .replace(/[ìíîï]/g, 'i')\n    .replace(/[òóôõö]/g, 'o')\n    .replace(/[ùúûü]/g, 'u')\n    .replace(/[ç]/g, 'c')\n    .replace(/[ñ]/g, 'n')\n    // Remove caracteres especiais\n    .replace(/[^\\w\\s-]/g, '')\n    // Substitui espaços e underscores por hífens\n    .replace(/[\\s_]+/g, '-')\n    // Remove hífens duplicados\n    .replace(/-+/g, '-')\n    // Remove hífens no início e fim\n    .replace(/^-+|-+$/g, '');\n}\n\n// ==========================================\n// 🔍 EXTRAÇÃO DE VALORES\n// ==========================================\n\n/**\n * Extrai valor de um campo, considerando diferentes formatos\n * Suporta campos diretos, operadores Prisma e campos aninhados\n */\nfunction extractFieldValue(filters: Record<string, any>, fieldNames: readonly string[]): string | null {\n  for (const fieldName of fieldNames) {\n    // Verifica campo direto\n    if (filters[fieldName]) {\n      const value = filters[fieldName];\n      \n      // String simples\n      if (typeof value === 'string') {\n        return value;\n      }\n      \n      // Operador Prisma { in: [...] } - pega o primeiro valor\n      if (value.in && Array.isArray(value.in) && value.in.length > 0) {\n        return value.in[0];\n      }\n      \n      // Operador Prisma { equals: \"...\" }\n      if (value.equals && typeof value.equals === 'string') {\n        return value.equals;\n      }\n    }\n    \n    // Verifica campo aninhado (ex: endereco.cidade)\n    if (fieldName.includes('.')) {\n      const parts = fieldName.split('.');\n      let current: any = filters;\n      \n      for (const part of parts) {\n        if (current && typeof current === 'object' && current[part]) {\n          current = current[part];\n        } else {\n          current = null;\n          break;\n        }\n      }\n      \n      if (current && typeof current === 'string') {\n        return current;\n      }\n    }\n  }\n  \n  return null;\n}\n\n// ==========================================\n// 🎯 FUNÇÕES PRINCIPAIS\n// ==========================================\n\n/**\n * Gera slug SEO básico baseado nos filtros\n * Extrai campos relevantes e gera slug no formato: tipo-operacao-bairro-cidade-estado\n */\nexport function generateSeoSlug(filters: Record<string, any>): string | null {\n  const slugParts: string[] = [];\n  \n  // Ordem específica para melhor SEO: tipo-subtipo-operacao-bairro-cidade-estado\n  const extractionOrder: (keyof typeof SEO_FIELDS)[] = [\n    'tipo', 'subtipo', 'operacao', 'bairro', 'cidade', 'estado'\n  ];\n  \n  for (const fieldType of extractionOrder) {\n    const fieldNames = SEO_FIELDS[fieldType];\n    const value = extractFieldValue(filters, fieldNames);\n    \n    if (value) {\n      const slugified = slugify(value);\n      if (slugified && slugified.length > 0) {\n        slugParts.push(slugified);\n      }\n    }\n  }\n  \n  // Só gera slug se tiver pelo menos 2 partes\n  if (slugParts.length >= 2) {\n    return slugParts.join('-');\n  }\n  \n  return null;\n}\n\n/**\n * Gera slug SEO completo com prefixo e limitação de tamanho\n */\nexport function generateSeoSlugWithOptions(\n  filters: Record<string, any>, \n  options?: SeoSlugOptions\n): string | null {\n  const baseSlug = generateSeoSlug(filters);\n  \n  if (!baseSlug) {\n    return null;\n  }\n  \n  let finalSlug = baseSlug;\n  \n  // Adiciona prefixo se especificado\n  if (options?.slugPrefix) {\n    const prefix = slugify(options.slugPrefix);\n    finalSlug = `${prefix}-${finalSlug}`;\n  }\n  \n  // Limita tamanho se especificado\n  const maxLength = options?.maxSlugLength || 100;\n  if (finalSlug.length > maxLength) {\n    // Trunca mantendo palavras completas\n    const truncated = finalSlug.substring(0, maxLength);\n    const lastHyphen = truncated.lastIndexOf('-');\n    finalSlug = lastHyphen > 0 ? truncated.substring(0, lastHyphen) : truncated;\n  }\n  \n  return finalSlug;\n}\n\n// ==========================================\n// 🌐 INTEGRAÇÃO COM URLS\n// ==========================================\n\n/**\n * Gera URL completa com slug SEO para uso em frontend\n * Combina slug SEO com query string de filtros\n */\nexport function generateSeoUrl(\n  filters: Record<string, any>,\n  queryString: string = '',\n  baseUrl: string = '/imoveis',\n  options?: SeoSlugOptions\n): string {\n  const slug = generateSeoSlugWithOptions(filters, options);\n  \n  if (slug) {\n    const url = `${baseUrl}/${slug}`;\n    return queryString ? `${url}?${queryString}` : url;\n  } else {\n    const url = baseUrl;\n    return queryString ? `${url}?${queryString}` : url;\n  }\n}\n\n// ==========================================\n// 🧪 UTILITÁRIOS DE TESTE E DEBUG\n// ==========================================\n\n/**\n * Testa geração de slug com diferentes tipos de filtros\n */\nexport function testSlugGeneration(filters: Record<string, any>): {\n  filters: Record<string, any>;\n  basicSlug: string | null;\n  withPrefix: string | null;\n  withOptions: string | null;\n  extractedFields: Record<string, string | null>;\n} {\n  const extractedFields: Record<string, string | null> = {};\n  \n  // Extrai todos os campos para debug\n  for (const [fieldType, fieldNames] of Object.entries(SEO_FIELDS)) {\n    extractedFields[fieldType] = extractFieldValue(filters, fieldNames);\n  }\n  \n  return {\n    filters,\n    basicSlug: generateSeoSlug(filters),\n    withPrefix: generateSeoSlugWithOptions(filters, { slugPrefix: 'imoveis' }),\n    withOptions: generateSeoSlugWithOptions(filters, { \n      slugPrefix: 'imoveis', \n      maxSlugLength: 50 \n    }),\n    extractedFields\n  };\n}\n\n/**\n * Valida se um slug é válido para SEO\n */\nexport function validateSeoSlug(slug: string): {\n  isValid: boolean;\n  issues: string[];\n  suggestions: string[];\n} {\n  const issues: string[] = [];\n  const suggestions: string[] = [];\n  \n  // Verifica tamanho\n  if (slug.length < 10) {\n    issues.push('Slug muito curto (< 10 caracteres)');\n    suggestions.push('Adicione mais informações relevantes');\n  }\n  \n  if (slug.length > 100) {\n    issues.push('Slug muito longo (> 100 caracteres)');\n    suggestions.push('Use maxSlugLength para limitar o tamanho');\n  }\n  \n  // Verifica caracteres inválidos\n  if (!/^[a-z0-9-]+$/.test(slug)) {\n    issues.push('Contém caracteres inválidos');\n    suggestions.push('Use apenas letras minúsculas, números e hífens');\n  }\n  \n  // Verifica hífens consecutivos ou nas bordas\n  if (slug.includes('--') || slug.startsWith('-') || slug.endsWith('-')) {\n    issues.push('Hífens mal formatados');\n    suggestions.push('Evite hífens consecutivos ou nas bordas');\n  }\n  \n  // Verifica quantidade de partes\n  const parts = slug.split('-');\n  if (parts.length < 2) {\n    issues.push('Poucas informações no slug');\n    suggestions.push('Inclua pelo menos tipo e localização');\n  }\n  \n  return {\n    isValid: issues.length === 0,\n    issues,\n    suggestions\n  };\n}\n\n// ==========================================\n// 📊 ESTATÍSTICAS E ANÁLISE\n// ==========================================\n\n/**\n * Analisa campos disponíveis nos filtros para geração de slug\n */\nexport function analyzeSeoFields(filters: Record<string, any>): {\n  availableFields: Record<string, string | null>;\n  missingFields: string[];\n  slugPotential: 'high' | 'medium' | 'low' | 'none';\n  recommendations: string[];\n} {\n  const availableFields: Record<string, string | null> = {};\n  const missingFields: string[] = [];\n  const recommendations: string[] = [];\n  \n  // Analisa cada tipo de campo\n  for (const [fieldType, fieldNames] of Object.entries(SEO_FIELDS)) {\n    const value = extractFieldValue(filters, fieldNames);\n    availableFields[fieldType] = value;\n    \n    if (!value) {\n      missingFields.push(fieldType);\n    }\n  }\n  \n  // Determina potencial do slug\n  const availableCount = Object.values(availableFields).filter(v => v !== null).length;\n  let slugPotential: 'high' | 'medium' | 'low' | 'none';\n  \n  if (availableCount >= 4) {\n    slugPotential = 'high';\n  } else if (availableCount >= 2) {\n    slugPotential = 'medium';\n    recommendations.push('Adicione mais campos de localização para melhor SEO');\n  } else if (availableCount === 1) {\n    slugPotential = 'low';\n    recommendations.push('Adicione pelo menos mais um campo relevante');\n  } else {\n    slugPotential = 'none';\n    recommendations.push('Adicione campos como tipo, cidade ou operação');\n  }\n  \n  // Recomendações específicas\n  if (!availableFields.tipo) {\n    recommendations.push('Adicione o tipo do imóvel (casa, apartamento, etc.)');\n  }\n  if (!availableFields.cidade) {\n    recommendations.push('Adicione a cidade para melhor SEO local');\n  }\n  if (!availableFields.operacao) {\n    recommendations.push('Especifique a operação (venda, aluguel)');\n  }\n  \n  return {\n    availableFields,\n    missingFields,\n    slugPotential,\n    recommendations\n  };\n}","/**\n * 🎨 Horizon Domain Data Display Enricher\n * \n * Enriquecedor genérico de dados de domínios para display\n * Transforma dados brutos de entidades em objetos enriquecidos para UI\n * \n * @module horizon-domain-data-display-enricher\n * @version 1.0.0\n */\n\nimport { format } from \"date-fns\";\nimport ptBR from \"date-fns/locale/pt-BR/index.js\";\n\n// ============================================\n// TYPES & INTERFACES\n// ============================================\n\nexport interface FieldMetadata {\n\tkey: string;\n\tlabel?: string;\n\ttype?: string;\n\tformat?: string;\n\tunit?: string;\n\tcategories?: string[];\n\tcomposedLabel?: string;\n\ticon?: string;\n\ticonName?: string;\n\tvalidation?: any;\n\t[key: string]: any; // Permite campos adicionais\n}\n\nexport interface EnrichmentOptions {\n\tdata: Record<string, any>;\n\tmetadata: FieldMetadata[];\n\tlocale?: string;\n\tcurrency?: string;\n\tgetIcon?: (iconName: string) => any;\n}\n\nexport interface EnrichedField extends FieldMetadata {\n\tvalue: any;\n\tvalueLabel?: string;\n\tcomposedLabel?: string;\n\ticon?: any;\n}\n\n// ============================================\n// FORMATTERS\n// ============================================\n\n/**\n * Formata valor monetário\n */\nfunction formatCurrency(\n\tvalue: number | string | null,\n\tcurrency = \"BRL\",\n\tlocale = \"pt-BR\"\n): string {\n\tif (value === null || value === undefined) {\n\t\treturn \"Valor sob consulta\";\n\t}\n\n\tconst numValue = Number(value);\n\tif (isNaN(numValue)) return String(value);\n\n\treturn numValue.toLocaleString(locale, {\n\t\tstyle: \"currency\",\n\t\tcurrency: currency,\n\t\tminimumFractionDigits: 2,\n\t});\n}\n\n/**\n * Formata data\n */\nfunction formatDateTime(value: string | Date, locale = \"pt-BR\"): string {\n\ttry {\n\t\tconst date = value instanceof Date ? value : new Date(value);\n\t\tif (isNaN(date.getTime())) return String(value);\n\n\t\t// Para pt-BR usa date-fns\n\t\tif (locale === \"pt-BR\") {\n\t\t\treturn format(date, \"d 'de' MMMM 'de' yyyy\", { locale: ptBR });\n\t\t}\n\n\t\t// Para outros locales usa toLocaleDateString\n\t\treturn date.toLocaleDateString(locale);\n\t} catch {\n\t\treturn String(value);\n\t}\n}\n\n/**\n * Formata área com unidade\n */\nfunction formatArea(value: number | string, unit = \"m²\"): string {\n\tif (value === null || value === undefined) return \"\";\n\t\n\tconst unitMap: Record<string, string> = {\n\t\t\"m2\": \"m²\",\n\t\t\"m²\": \"m²\",\n\t\t\"ft2\": \"ft²\",\n\t\t\"hectare\": \"hectares\",\n\t\t\"hectares\": \"hectares\",\n\t\t\"km2\": \"km²\"\n\t};\n\n\tconst displayUnit = unitMap[unit] || unit;\n\treturn `${value} ${displayUnit}`;\n}\n\n/**\n * Formata distância com unidade\n */\nfunction formatDistance(value: number | string, unit = \"m\"): string {\n\tif (value === null || value === undefined) return \"\";\n\t\n\tconst unitMap: Record<string, string> = {\n\t\t\"m\": \"m\",\n\t\t\"meters\": \"m\",\n\t\t\"km\": \"km\",\n\t\t\"mi\": \"mi\",\n\t\t\"miles\": \"mi\"\n\t};\n\n\tconst displayUnit = unitMap[unit] || unit;\n\treturn `${value}${displayUnit}`;\n}\n\n/**\n * Formata porcentagem\n */\nfunction formatPercent(value: number | string): string {\n\tif (value === null || value === undefined) return \"\";\n\t\n\tconst numValue = Number(value);\n\tif (isNaN(numValue)) return String(value);\n\n\t// Se o valor já estiver em porcentagem (ex: 15 para 15%)\n\tif (numValue > 1) {\n\t\treturn `${numValue}%`;\n\t}\n\t\n\t// Se o valor estiver em decimal (ex: 0.15 para 15%)\n\treturn `${(numValue * 100).toFixed(2)}%`;\n}\n\n/**\n * Formata contagem (números inteiros)\n */\nfunction formatCount(value: number | string): string {\n\tif (value === null || value === undefined) return \"0\";\n\treturn String(Math.floor(Number(value)));\n}\n\n/**\n * Formata ano\n */\nfunction formatYear(value: number | string): string {\n\tif (value === null || value === undefined) return \"\";\n\treturn String(value);\n}\n\n// ============================================\n// TEMPLATE PROCESSING\n// ============================================\n\n/**\n * Processa template com pluralização e substituições\n */\nfunction processTemplate(\n\ttemplate: string | undefined,\n\tvalue: any,\n\tvalueLabel: string\n): string | undefined {\n\tif (!template) return undefined;\n\n\tlet result = template;\n\n\t// Substitui valor bruto\n\tresult = result.replace(/{{value}}/g, String(value));\n\n\t// Substitui valor formatado\n\tresult = result.replace(/{{valueLabel}}/g, valueLabel);\n\n\t// Processa pluralização {{p:texto}}\n\tresult = result.replace(/{{p:(.*?)}}/g, (_, plural) => {\n\t\tconst numValue = Number(value);\n\t\treturn numValue !== 1 ? plural : \"\";\n\t});\n\n\t// Processa singular {{s:texto}}\n\tresult = result.replace(/{{s:(.*?)}}/g, (_, singular) => {\n\t\tconst numValue = Number(value);\n\t\treturn numValue === 1 ? singular : \"\";\n\t});\n\n\treturn result;\n}\n\n// ============================================\n// VALUE LABEL GENERATION\n// ============================================\n\n/**\n * Gera label formatado para o valor baseado no tipo e formato\n * Só gera valueLabel quando realmente necessário para formatação especial\n */\nfunction generateValueLabel(field: EnrichedField, options: Partial<EnrichmentOptions> = {}): string | undefined {\n\tconst { value, format, unit, type, enum: enumValues } = field;\n\tconst { locale = \"pt-BR\", currency = \"BRL\" } = options;\n\n\t// Se não houver valor\n\tif (value === null || value === undefined) {\n\t\tif (format === \"currency\") return \"Valor sob consulta\";\n\t\treturn undefined;\n\t}\n\n\t// Se já tiver valueLabel definido, usa ele\n\tif (field.valueLabel) {\n\t\treturn field.valueLabel;\n\t}\n\n\t// Formatação baseada no format - apenas casos que precisam de transformação\n\tswitch (format) {\n\t\tcase \"currency\":\n\t\t\treturn formatCurrency(value, unit || currency, locale);\n\n\t\tcase \"date\":\n\t\tcase \"datetime\":\n\t\t\treturn formatDateTime(value, locale);\n\n\t\tcase \"area\":\n\t\t\treturn formatArea(value, unit);\n\n\t\tcase \"distance\":\n\t\t\treturn formatDistance(value, unit);\n\n\t\tcase \"percent\":\n\t\t\treturn formatPercent(value);\n\n\t\tcase \"count\":\n\t\t\treturn formatCount(value);\n\n\t\tcase \"year\":\n\t\t\treturn formatYear(value);\n\t}\n\n\t// Para tipos específicos que precisam de transformação\n\tif (type === \"Boolean\") {\n\t\treturn value ? \"Sim\" : \"Não\";\n\t}\n\n\t// Arrays: só gerar valueLabel se tiver enum (mapeamento)\n\tif (type === \"String[]\" && Array.isArray(value)) {\n\t\t// Se NÃO tem enum, deixa o frontend decidir como formatar\n\t\tif (!enumValues || typeof enumValues !== 'object') {\n\t\t\treturn undefined;\n\t\t}\n\t\t\n\t\t// Se tem enum, mapeia os valores para labels e formata\n\t\tlet values = value.map(v => enumValues[v] || v);\n\t\t\n\t\t// Formatação correta em português brasileiro\n\t\tif (values.length === 0) return \"\";\n\t\tif (values.length === 1) return values[0];\n\t\tif (values.length === 2) return `${values[0]} e ${values[1]}`;\n\t\t\n\t\t// 3+ itens: \"A, B e C\"\n\t\tconst lastItem = values[values.length - 1];\n\t\tconst otherItems = values.slice(0, -1).join(\", \");\n\t\treturn `${otherItems} e ${lastItem}`;\n\t}\n\n\t// String simples com enum: mapear valor para label\n\tif (type === \"String\" && enumValues && typeof enumValues === 'object') {\n\t\treturn enumValues[value] || value; // Mapeia ou mantém original se não encontrar\n\t}\n\n\t// Para JSON: NÃO gerar valueLabel - deixar o frontend decidir como renderizar\n\tif (type === \"Json\") {\n\t\treturn undefined; // Frontend deve processar JSON objects\n\t}\n\n\t// Para Array/Json[]: apenas se for array simples de strings\n\tif (type === \"Array\" || type === \"Json[]\") {\n\t\tif (Array.isArray(value) && value.every(item => typeof item === 'string')) {\n\t\t\treturn value.join(\", \");\n\t\t}\n\t\treturn undefined; // Arrays complexos: deixar o frontend decidir\n\t}\n\n\t// Para strings simples e números simples: NÃO gera valueLabel\n\t// Eles usarão o valor original\n\treturn undefined;\n}\n\n// ============================================\n// MAIN ENRICHMENT FUNCTION\n// ============================================\n\n/**\n * Enriquece campos individuais com metadados\n */\nfunction enrichField(\n\tfieldValue: any,\n\tmetadata: FieldMetadata,\n\toptions: Partial<EnrichmentOptions> = {}\n): EnrichedField {\n\t// Extrair composedLabel e iconName para controlar ordem\n\tconst { \n\t\tcomposedLabel: originalComposedLabel, \n\t\ticonName: originalIconName, \n\t\t...baseMetadata \n\t} = metadata;\n\n\t// Criar objeto resultado com ordem específica\n\tconst result: any = {};\n\n\t// SEGUINDO A ORDEM EXATA DA ESPECIFICAÇÃO (23 metadados)\n\n\t// 1. IDENTIFICAÇÃO BÁSICA\n\tif (baseMetadata.key) result.key = baseMetadata.key;\n\tif (baseMetadata.label) result.label = baseMetadata.label;\n\tif (baseMetadata.description) result.description = baseMetadata.description;\n\tif (baseMetadata.enum) result.enum = baseMetadata.enum;\n\tif (baseMetadata.type) result.type = baseMetadata.type;\n\n\t// 2. FORMATAÇÃO BÁSICA\n\tif (baseMetadata.format) result.format = baseMetadata.format;\n\tif (baseMetadata.unit) result.unit = baseMetadata.unit;\n\n\t// 3. VALIDAÇÃO E BANCO\n\tif (baseMetadata.validation) result.validation = baseMetadata.validation;\n\tif (baseMetadata.db) result.db = baseMetadata.db;\n\n\t// 4. COMPORTAMENTO DE BUSCA\n\tif (baseMetadata.searchable !== undefined) result.searchable = baseMetadata.searchable;\n\tif (baseMetadata.filterable !== undefined) result.filterable = baseMetadata.filterable;\n\tif (baseMetadata.sortable !== undefined) result.sortable = baseMetadata.sortable;\n\n\t// 5. RELAÇÕES E DEPENDÊNCIAS\n\tif (baseMetadata.parent) result.parent = baseMetadata.parent;\n\tif (baseMetadata.conditions) result.conditions = baseMetadata.conditions;\n\n\t// 6. DISPLAY/UI (ordem específica: value → valueLabel → composedLabel → icon)\n\tresult.value = fieldValue;\n\t\n\tconst valueLabel = generateValueLabel({ value: fieldValue, ...metadata }, options);\n\tif (valueLabel) {\n\t\tresult.valueLabel = valueLabel;\n\t}\n\t\n\tif (originalComposedLabel) {\n\t\tconst processed = processTemplate(originalComposedLabel, fieldValue, valueLabel || String(fieldValue));\n\t\tif (processed) {\n\t\t\tresult.composedLabel = processed;\n\t\t}\n\t}\n\n\tif (originalIconName) result.iconName = originalIconName;\n\tif (originalIconName && options.getIcon) {\n\t\tconst icon = options.getIcon(originalIconName);\n\t\tif (icon) result.icon = icon;\n\t}\n\n\t// 7. FORMULÁRIOS\n\tif (baseMetadata.mask) result.mask = baseMetadata.mask;\n\tif (baseMetadata.placeholder) result.placeholder = baseMetadata.placeholder;\n\n\t// 8. CATEGORIZAÇÃO\n\tif (baseMetadata.categories) result.categories = baseMetadata.categories;\n\n\t// 9. AUDITORIA\n\tif (baseMetadata.origin) result.origin = baseMetadata.origin;\n\tif (baseMetadata.modifiedBy) result.modifiedBy = baseMetadata.modifiedBy;\n\n\treturn result as EnrichedField;\n}\n\n/**\n * Função principal de enriquecimento de dados\n * \n * @param options - Opções de enriquecimento\n * @returns Dados enriquecidos com metadados\n */\nexport function domainDataDisplayEnricher(options: EnrichmentOptions): Record<string, any> {\n\tconst { data, metadata, ...enrichOptions } = options;\n\n\t// Cria cópia dos dados\n\tconst enrichedData = { ...data };\n\n\t// Processa cada campo que tem metadata\n\tmetadata.forEach((fieldMetadata) => {\n\t\tconst fieldKey = fieldMetadata.key;\n\n\t\t// Se o campo existe nos dados\n\t\tif (fieldKey in enrichedData) {\n\t\t\tconst fieldValue = enrichedData[fieldKey];\n\n\t\t\t// Se o valor for undefined, mantém como está\n\t\t\tif (fieldValue === undefined) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Enriquece o campo\n\t\t\tenrichedData[fieldKey] = enrichField(fieldValue, fieldMetadata, enrichOptions);\n\t\t}\n\t});\n\n\treturn enrichedData;\n}\n\n// ============================================\n// UTILITY EXPORTS\n// ============================================\n\nexport const formatters = {\n\tcurrency: formatCurrency,\n\tdate: formatDateTime,\n\tarea: formatArea,\n\tdistance: formatDistance,\n\tpercent: formatPercent,\n\tcount: formatCount,\n\tyear: formatYear,\n};\n\nexport const templateProcessor = processTemplate;\n\n// ============================================\n// BACKWARD COMPATIBILITY\n// ============================================\n\n/**\n * Função de compatibilidade com a API antiga\n * @deprecated Use domainDataDisplayEnricher instead\n */\nexport function EnrichFieldsWithMetadata({ \n\tdata, \n\tmetadata \n}: { \n\tdata: any; \n\tmetadata: any[] \n}): any {\n\treturn domainDataDisplayEnricher({ data, metadata });\n}\n\n// Default export\nexport default domainDataDisplayEnricher;","/**\n * JsonToZodGenerator - Converte schemas Horizon Fields Metadata Pattern v2.2.0 para Zod\n * \n * Suporta o novo formato com:\n * - categories (ao invés de tags)\n * - validation.precision para decimais\n * - enum como object\n * - mask para validações automáticas\n * - conditions para campos condicionais\n * - parent para hierarquias\n * - db metadata (ignorado na geração Zod)\n * - Inferência inteligente\n */\n\nexport interface HorizonFieldDefinition {\n  key: string\n  type: \"String\" | \"String[]\" | \"Number\" | \"Boolean\" | \"Json\" | \"Json[]\" | \"Array\"\n  label: string\n  categories?: string[]\n  \n  // Validação\n  validation?: {\n    required?: boolean\n    min?: number\n    max?: number\n    minLength?: number\n    maxLength?: number\n    precision?: number  // Novo campo para decimais\n  }\n  \n  // Formato e apresentação\n  format?: \"currency\" | \"area\" | \"distance\" | \"count\" | \"percent\" | \"date\" | \"datetime\" | \"time\"\n  unit?: string\n  mask?: \"cpf\" | \"cnpj\" | \"cep\" | \"phone\" | \"email\" | \"url\"  // Frontend only! Backend recebe dados limpos\n  \n  // Enum novo formato (object)\n  enum?: Record<string, string>\n  \n  // Relações e dependências\n  conditions?: string[]  // [\"operacao:venda\", \"tipo.equals:apartamento\"]\n  parent?: string\n  \n  // UI/UX\n  searchable?: boolean\n  filterable?: boolean\n  sortable?: boolean\n  \n  // DB (ignorado na geração Zod)\n  db?: {\n    type?: string\n    unique?: boolean\n    index?: boolean | string\n    default?: any\n  }\n  \n  // Auditoria\n  origin?: string\n  modifiedBy?: string[]\n}\n\nexport interface JsonToZodOptions {\n  schemaName: string\n  addDescriptions?: boolean\n  addValidationMessages?: boolean\n  exportType?: boolean\n  sortFields?: boolean\n  \n  // Novos options v2\n  enablePrecisionValidation?: boolean  // Gerar .multipleOf() para precision\n  // MASK É SÓ FRONTEND! Backend recebe dados limpos\n  // CONDITIONS É SÓ FRONTEND! (controle de exibição de campos)\n  logInference?: boolean               // Log das inferências realizadas\n}\n\nexport class JsonToZodGenerator {\n  private static inferenceLog: string[] = []\n  \n  /**\n   * Aplica inferência inteligente em um campo\n   */\n  private static applyInference(field: HorizonFieldDefinition, options: JsonToZodOptions): HorizonFieldDefinition {\n    const inferredField = { ...field }\n    \n    if (options.logInference) {\n      this.inferenceLog = []\n    }\n    \n    // Inferência de precision para multipleOf\n    if (field.validation?.precision && options.enablePrecisionValidation) {\n      const multipleOf = Math.pow(10, -field.validation.precision)\n      this.log(`🔢 ${field.key}: precision ${field.validation.precision} → multipleOf ${multipleOf}`)\n    }\n    \n    // MASK É SÓ PARA FRONTEND! Backend recebe dados limpos\n    if (field.mask) {\n      this.log(`🎭 ${field.key}: mask \"${field.mask}\" → FRONTEND ONLY (backend receives clean data)`)\n    }\n    \n    // Inferência de tipos especiais\n    if (field.type === 'Json') {\n      this.log(`📦 ${field.key}: Json type → z.any() or z.record()`)\n    }\n    \n    // Inferência para arrays\n    if (field.type === 'String[]' && field.searchable) {\n      this.log(`🔍 ${field.key}: String[] + searchable → GIN index (DB only)`)\n    }\n    \n    // Inferência para campos de texto longo\n    if (field.type === 'String' && field.searchable && !field.validation?.maxLength) {\n      this.log(`📝 ${field.key}: String + searchable + no maxLength → fulltext index (DB only)`)\n    }\n    \n    return inferredField\n  }\n  \n  private static log(message: string) {\n    this.inferenceLog.push(message)\n  }\n  \n  \n  /**\n   * Converte um campo para Zod\n   */\n  private static fieldToZod(field: HorizonFieldDefinition, options: JsonToZodOptions): string {\n    // Aplicar inferência\n    const processedField = this.applyInference(field, options)\n    \n    const { key, type, label, validation, enum: enumValues } = processedField\n    \n    let zodType = ''\n    let validations: string[] = []\n    \n    // Mapear tipos base\n    switch (type) {\n      case 'String':\n        if (enumValues && Object.keys(enumValues).length > 0) {\n          // Enum com novo formato object\n          const enumArray = Object.keys(enumValues).map(k => `\"${k}\"`).join(', ')\n          zodType = `z.enum([${enumArray}])`\n        } else {\n          zodType = 'z.string()'\n        }\n        \n        // Validações de string\n        if (validation?.minLength) validations.push(`.min(${validation.minLength})`)\n        if (validation?.maxLength) validations.push(`.max(${validation.maxLength})`)\n        \n        // MASK É SÓ PARA FRONTEND! Backend recebe dados limpos\n        break\n        \n      case 'Number':\n        zodType = 'z.number()'\n        \n        // Validações numéricas\n        if (validation?.min !== undefined) validations.push(`.min(${validation.min})`)\n        if (validation?.max !== undefined) validations.push(`.max(${validation.max})`)\n        \n        // Precision para multipleOf\n        if (validation?.precision && options.enablePrecisionValidation) {\n          const multipleOf = Math.pow(10, -validation.precision)\n          validations.push(`.multipleOf(${multipleOf})`)\n        }\n        break\n        \n      case 'Boolean':\n        zodType = 'z.boolean()'\n        break\n        \n      case 'String[]':\n        if (enumValues && Object.keys(enumValues).length > 0) {\n          // Array de enum\n          const enumArray = Object.keys(enumValues).map(k => `\"${k}\"`).join(', ')\n          zodType = `z.array(z.enum([${enumArray}]))`\n        } else {\n          zodType = 'z.array(z.string())'\n        }\n        break\n        \n      case 'Array':\n        zodType = 'z.array(z.any())'\n        break\n        \n      case 'Json':\n        // Objeto JSON único\n        zodType = 'z.any()' // ou z.record(z.any()) dependendo do uso\n        break\n        \n      case 'Json[]':\n        // Array de objetos JSON\n        zodType = 'z.array(z.any())'\n        break\n        \n      default:\n        zodType = 'z.any()'\n    }\n    \n    // Adicionar validações\n    zodType += validations.join('')\n    \n    // Adicionar descrição se habilitado\n    if (options.addDescriptions && label) {\n      zodType += `.describe(\"${label}\")`\n    }\n    \n    // Required/Optional\n    if (!validation?.required) {\n      zodType += '.optional()'\n    }\n    \n    return `  ${key}: ${zodType},`\n  }\n  \n  \n  /**\n   * Gera o schema Zod completo\n   */\n  static generate(fields: HorizonFieldDefinition[], options: JsonToZodOptions): string {\n    const { \n      schemaName, \n      sortFields = false, \n      exportType = true,\n      logInference = false\n    } = options\n    \n    if (logInference) {\n      console.log(`\\n🧠 INICIANDO GERAÇÃO COM INFERÊNCIA - ${schemaName}`)\n      console.log(`📊 Total de campos: ${fields.length}`)\n    }\n    \n    // Ordenar campos se solicitado\n    const processedFields = sortFields \n      ? [...fields].sort((a, b) => a.key.localeCompare(b.key))\n      : fields\n    \n    // Gerar imports\n    const imports = `import { z } from \"zod\"\\n`\n    \n    // Gerar campos do schema\n    const schemaFields = processedFields\n      .map(field => this.fieldToZod(field, options))\n      .join('\\n')\n    \n    // Gerar schema base\n    const schema = `\n// Schema Horizon v2.2.0 para ${schemaName}\n// Gerado automaticamente com inferência inteligente\nexport const ${schemaName}Zod = z.object({\n${schemaFields}\n})\n`\n    \n    // CONDITIONS É SÓ PARA FRONTEND! (controle de exibição de campos)\n    \n    // Gerar tipo TypeScript se solicitado\n    const typeExport = exportType \n      ? `\n// Tipo inferido a partir do schema\nexport type ${schemaName}Type = z.infer<typeof ${schemaName}Zod>\n\n// Função helper para validação\nexport const validate${schemaName} = (data: unknown): ${schemaName}Type => {\n  return ${schemaName}Zod.parse(data)\n}\n\n// Função helper para validação safe\nexport const safeValidate${schemaName} = (data: unknown) => {\n  return ${schemaName}Zod.safeParse(data)\n}\n\n// Função helper para validação parcial\nexport const validatePartial${schemaName} = (data: unknown) => {\n  return ${schemaName}Zod.partial().parse(data)\n}\n`\n      : ''\n    \n    // Log das inferências\n    if (logInference && this.inferenceLog.length > 0) {\n      console.log(`\\n🧠 INFERÊNCIAS APLICADAS:`)\n      this.inferenceLog.forEach(log => console.log(log))\n      console.log(`\\n✅ Geração concluída com ${this.inferenceLog.length} inferências`)\n    }\n    \n    return imports + schema + typeExport\n  }\n  \n  /**\n   * Gera schema a partir de arquivo JSON v2.2.0\n   */\n  static async generateFromFile(jsonPath: string, options: JsonToZodOptions): Promise<string> {\n    const fs = await import('fs/promises')\n    const jsonContent = await fs.readFile(jsonPath, 'utf-8')\n    const data = JSON.parse(jsonContent)\n    \n    // Suporta formato { fields: [...] }\n    const fields = data.fields || data\n    \n    if (!Array.isArray(fields)) {\n      throw new Error('JSON deve conter um array de campos ou objeto com propriedade \"fields\"')\n    }\n    \n    return this.generate(fields, options)\n  }\n  \n  /**\n   * Salva o schema gerado\n   */\n  static async saveToFile(\n    fields: HorizonFieldDefinition[], \n    options: JsonToZodOptions, \n    outputPath: string\n  ): Promise<void> {\n    const fs = await import('fs/promises')\n    const path = await import('path')\n    \n    const generated = this.generate(fields, options)\n    \n    // Criar diretório se não existir\n    const dir = path.dirname(outputPath)\n    await fs.mkdir(dir, { recursive: true })\n    \n    // Salvar arquivo\n    await fs.writeFile(outputPath, generated, 'utf-8')\n    \n    if (options.logInference) {\n      console.log(`\\n💾 Schema salvo: ${outputPath}`)\n    }\n  }\n  \n  /**\n   * Analisa um schema e retorna estatísticas\n   */\n  static analyzeSchema(fields: HorizonFieldDefinition[]): {\n    totalFields: number\n    fieldTypes: Record<string, number>\n    fieldFormats: Record<string, number>\n    fieldCategories: Record<string, number>\n    requiredFields: number\n    fieldsWithValidation: number\n    fieldsWithMask: number\n    fieldsWithEnum: number\n    fieldsWithConditions: number\n    fieldsWithParent: number\n  } {\n    const analysis = {\n      totalFields: fields.length,\n      fieldTypes: {} as Record<string, number>,\n      fieldFormats: {} as Record<string, number>,\n      fieldCategories: {} as Record<string, number>,\n      requiredFields: 0,\n      fieldsWithValidation: 0,\n      fieldsWithMask: 0,\n      fieldsWithEnum: 0,\n      fieldsWithConditions: 0,\n      fieldsWithParent: 0\n    }\n    \n    fields.forEach(field => {\n      // Tipos\n      analysis.fieldTypes[field.type] = (analysis.fieldTypes[field.type] || 0) + 1\n      \n      // Formatos\n      if (field.format) {\n        analysis.fieldFormats[field.format] = (analysis.fieldFormats[field.format] || 0) + 1\n      }\n      \n      // Categorias\n      if (field.categories) {\n        field.categories.forEach(cat => {\n          analysis.fieldCategories[cat] = (analysis.fieldCategories[cat] || 0) + 1\n        })\n      }\n      \n      // Contadores\n      if (field.validation?.required) analysis.requiredFields++\n      if (field.validation) analysis.fieldsWithValidation++\n      if (field.mask) analysis.fieldsWithMask++\n      if (field.enum) analysis.fieldsWithEnum++\n      if (field.conditions) analysis.fieldsWithConditions++\n      if (field.parent) analysis.fieldsWithParent++\n    })\n    \n    return analysis\n  }\n}\n\n// Re-exportar tipos para conveniência\nexport type { JsonToZodOptions as GeneratorOptions }","/**\n * 🔍 Horizon Domain Data Filters\n * \n * Funções utilitárias para filtrar e selecionar campos de dados de domínio\n * Compatível com formato array e objeto enriquecido\n * \n * @module horizon-domain-data-filters\n * @version 1.0.0\n */\n\n// ============================================\n// TYPES & INTERFACES\n// ============================================\n\nexport interface Field {\n\tkey: string;\n\tvalue?: any;\n\tlabel?: string;\n\ttype?: string;\n\tcategory?: string | string[];\n\tcategories?: string | string[];\n\t[key: string]: any;\n}\n\nexport type FieldsArray = Field[];\nexport type FieldsObject = Record<string, Field>;\nexport type FieldsInput = FieldsArray | FieldsObject;\n\n// ============================================\n// FILTER FUNCTIONS\n// ============================================\n\n/**\n * Filtra campos por categoria(s)\n * \n * @param fields - Array de campos ou objeto de campos enriquecidos\n * @param category - String de categoria única ou array de categorias\n * @param asObject - Se true, retorna como objeto; se false, retorna como array\n * @param preserveOrder - Se true, preserva a ordem das categorias solicitadas (padrão: false)\n * @returns Campos filtrados como array ou objeto\n * \n * @example\n * // Filtrar por categoria única\n * const mainFields = getFieldsByCategory(fields, 'main');\n * \n * @example\n * // Filtrar por múltiplas categorias\n * const valueFields = getFieldsByCategory(fields, ['pricing', 'values']);\n * \n * @example\n * // Retornar como objeto\n * const fieldsObj = getFieldsByCategory(fields, 'main', true);\n * \n * @example\n * // Preservar ordem das categorias solicitadas\n * const orderedFields = getFieldsByCategory(fields, ['pricing', 'dimensions'], false, true);\n * // Retorna todos os campos 'pricing' primeiro, depois todos os 'dimensions'\n */\nexport function getFieldsByCategory(\n\tfields: FieldsInput,\n\tcategory: string | string[],\n\tasObject: boolean = false,\n\tpreserveOrder: boolean = false\n): FieldsArray | FieldsObject {\n\t\n\t// Função helper para verificar match de categoria\n\tconst matchesCategory = (fieldCategory: string | string[] | undefined): boolean => {\n\t\tif (!fieldCategory) return false;\n\t\t\n\t\t// Normalizar para sempre trabalhar com arrays\n\t\tconst fieldCats = Array.isArray(fieldCategory) ? fieldCategory : [fieldCategory];\n\t\tconst searchCats = Array.isArray(category) ? category : [category];\n\t\t\n\t\t// Verificar se alguma categoria do campo está nas categorias buscadas\n\t\treturn fieldCats.some(cat => searchCats.includes(cat));\n\t};\n\t\n\t// Função helper para extrair categoria do campo\n\tconst getFieldCategory = (field: Field): string | string[] | undefined => {\n\t\t// Suporta tanto 'category' quanto 'categories' como nome do campo\n\t\treturn field?.categories || field?.category;\n\t};\n\t\n\t// Processar baseado no tipo de input\n\tlet matchingFields: FieldsArray;\n\t\n\tif (preserveOrder && Array.isArray(category)) {\n\t\t// Se preserveOrder é true e temos múltiplas categorias, ordenar pela ordem das categorias\n\t\tconst allFields = Array.isArray(fields) ? fields : Object.values(fields);\n\t\tmatchingFields = [];\n\t\t\n\t\t// Para cada categoria na ordem solicitada\n\t\tfor (const cat of category) {\n\t\t\t// Adicionar todos os campos dessa categoria\n\t\t\tconst categoryFields = allFields.filter(field => {\n\t\t\t\tconst fieldCat = getFieldCategory(field);\n\t\t\t\tif (!fieldCat) return false;\n\t\t\t\t\n\t\t\t\t// Check se o campo tem exatamente essa categoria\n\t\t\t\tif (Array.isArray(fieldCat)) {\n\t\t\t\t\treturn fieldCat.includes(cat);\n\t\t\t\t}\n\t\t\t\treturn fieldCat === cat;\n\t\t\t});\n\t\t\t\n\t\t\t// Adicionar apenas campos que ainda não foram adicionados (evitar duplicatas)\n\t\t\tcategoryFields.forEach(field => {\n\t\t\t\tif (!matchingFields.some(f => f.key === field.key)) {\n\t\t\t\t\tmatchingFields.push(field);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t} else {\n\t\t// Comportamento padrão: filtrar mantendo ordem original\n\t\tif (Array.isArray(fields)) {\n\t\t\t// Formato array: filtrar diretamente\n\t\t\tmatchingFields = fields.filter(field => \n\t\t\t\tmatchesCategory(getFieldCategory(field))\n\t\t\t);\n\t\t} else {\n\t\t\t// Formato objeto: converter valores para array e filtrar\n\t\t\tmatchingFields = Object.values(fields).filter(field =>\n\t\t\t\tmatchesCategory(getFieldCategory(field))\n\t\t\t);\n\t\t}\n\t}\n\t\n\t// Retornar no formato solicitado\n\tif (asObject) {\n\t\tconst result: FieldsObject = {};\n\t\tmatchingFields.forEach(field => {\n\t\t\tresult[field.key] = field;\n\t\t});\n\t\treturn result;\n\t}\n\t\n\treturn matchingFields;\n}\n\n/**\n * Filtra campos por lista de keys, mantendo a ordem especificada\n * Retorna apenas campos com valores válidos (não null, undefined, empty string ou NaN)\n * \n * @param fields - Array de campos ou objeto de campos enriquecidos\n * @param keys - Array de keys na ordem desejada\n * @param asObject - Se true, retorna como objeto; se false, retorna como array (padrão)\n * @returns Array ou objeto de campos na ordem das keys, apenas com valores válidos\n * \n * @example\n * // Buscar campos específicos na ordem desejada (array)\n * const orderedFields = getFieldsByKeys(fields, ['valor_venda', 'area_total', 'dormitorios']);\n * \n * @example\n * // Retornar como objeto para lookup rápido\n * const fieldsObj = getFieldsByKeys(fields, ['valor_venda', 'area_total'], true);\n * \n * @example\n * // Campos sem valores válidos são ignorados\n * const validFields = getFieldsByKeys(fields, ['field1', 'field2', 'field3']);\n * // Se field2.value for null, ele não aparece no resultado\n */\nexport function getFieldsByKeys(\n\tfields: FieldsInput,\n\tkeys: string[],\n\tasObject: boolean = false\n): FieldsArray | FieldsObject {\n\t\n\tif (!Array.isArray(keys) || keys.length === 0) {\n\t\treturn asObject ? {} : [];\n\t}\n\t\n\t// Função helper para verificar se tem valor válido\n\tconst hasValidValue = (field: Field | undefined): boolean => {\n\t\tif (!field) return false;\n\t\t\n\t\tconst value = field.value;\n\t\t\n\t\t// Considera inválido se for:\n\t\t// - null\n\t\t// - undefined\n\t\t// - string vazia\n\t\t// - NaN\n\t\tif (value === null || value === undefined || value === '' || Number.isNaN(value)) {\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\t// Arrays vazios também são considerados inválidos\n\t\tif (Array.isArray(value) && value.length === 0) {\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\treturn true;\n\t};\n\t\n\t// Criar mapa para acesso rápido\n\tlet fieldsMap: Map<string, Field>;\n\t\n\tif (Array.isArray(fields)) {\n\t\t// Formato array: criar mapa a partir do array\n\t\tfieldsMap = new Map(fields.map(field => [field.key, field]));\n\t} else {\n\t\t// Formato objeto: criar mapa a partir do objeto\n\t\tfieldsMap = new Map(Object.entries(fields));\n\t}\n\t\n\t// Mapear keys para campos, mantendo ordem e filtrando inválidos\n\tconst matchingFields = keys\n\t\t.map(key => fieldsMap.get(key))\n\t\t.filter((field): field is Field => hasValidValue(field));\n\t\n\t// Retornar no formato solicitado\n\tif (asObject) {\n\t\tconst result: FieldsObject = {};\n\t\tmatchingFields.forEach(field => {\n\t\t\tresult[field.key] = field;\n\t\t});\n\t\treturn result;\n\t}\n\t\n\treturn matchingFields;\n}\n\n// ============================================\n// EXPORTS\n// ============================================\n\nexport default {\n\tgetFieldsByCategory,\n\tgetFieldsByKeys\n};","/**\n * 🔄 Horizon Domain Data Transformers\n * \n * Funções para transformar estruturas de dados de domínio\n * \n * @module horizon-domain-data-transformers\n * @version 1.0.0\n */\n\n// ============================================\n// TYPES & INTERFACES\n// ============================================\n\nexport interface Field {\n\tkey: string;\n\tvalue?: any;\n\tlabel?: string;\n\ttype?: string;\n\t[key: string]: any;\n}\n\n// ============================================\n// TRANSFORM FUNCTIONS\n// ============================================\n\n/**\n * Expande um campo array em múltiplos campos booleanos\n * Cada item do array se torna um campo independente com value: true\n * \n * @param field - Campo com value array ou diretamente um array de strings\n * @returns Array de campos booleanos\n * \n * @example\n * // Passando campo completo\n * const field = { key: 'amenities', value: ['pool', 'gym', 'parking'] };\n * const booleans = expandArrayFieldToBoolean(field);\n * // Resultado: [\n * //   { key: 'pool', value: true, type: 'Boolean', label: 'pool' },\n * //   { key: 'gym', value: true, type: 'Boolean', label: 'gym' },\n * //   { key: 'parking', value: true, type: 'Boolean', label: 'parking' }\n * // ]\n * \n * @example\n * // Passando array direto\n * const booleans = expandArrayFieldToBoolean(['wifi', 'ac', 'tv']);\n * // Resultado: [\n * //   { key: 'wifi', value: true, type: 'Boolean', label: 'wifi' },\n * //   { key: 'ac', value: true, type: 'Boolean', label: 'ac' },\n * //   { key: 'tv', value: true, type: 'Boolean', label: 'tv' }\n * // ]\n * \n * @example\n * // Uso direto com propriedade\n * const property = { amenities: { key: 'amenities', value: ['pool', 'gym'] } };\n * const booleans = expandArrayFieldToBoolean(property.amenities);\n */\nexport function expandArrayFieldToBoolean(field: Field | string[]): Field[] {\n\t// Se receber array direto de strings\n\tif (Array.isArray(field)) {\n\t\treturn field.map(item => ({\n\t\t\tkey: String(item),\n\t\t\tvalue: true,\n\t\t\ttype: 'Boolean',\n\t\t\tlabel: String(item)\n\t\t}));\n\t}\n\t\n\t// Se receber campo com value array\n\tif (field && field.value && Array.isArray(field.value)) {\n\t\treturn field.value.map(item => ({\n\t\t\tkey: String(item),\n\t\t\tvalue: true,\n\t\t\ttype: 'Boolean',\n\t\t\tlabel: String(item)\n\t\t}));\n\t}\n\t\n\t// Se não for array válido, retorna array vazio\n\treturn [];\n}\n\n/**\n * Ordena um array de objetos baseado em múltiplos campos e direções\n * \n * @param fields - Array de objetos para ordenar\n * @param sortKeys - Array de strings no formato \"campo:direção\" (ex: [\"name:asc\", \"price:desc\"])\n * @returns Array ordenado (nova instância, não modifica o original)\n * \n * @example\n * // Ordenar por nome crescente, depois preço decrescente\n * const products = [\n *   { name: \"Casa A\", price: 300000, area: 120 },\n *   { name: \"Casa B\", price: 250000, area: 100 },\n *   { name: \"Casa A\", price: 280000, area: 110 }\n * ];\n * \n * const sorted = sortFields(products, [\"name:asc\", \"price:desc\"]);\n * // Resultado: Casa A (300k), Casa A (280k), Casa B (250k)\n * \n * @example\n * // Ordenar apenas por um campo\n * const sorted = sortFields(products, [\"area:desc\"]);\n */\nexport function sortFields(fields: any[], sortKeys: string[] = []): any[] {\n    return [...fields].sort((a, b) => {\n        for (const rule of sortKeys) {\n            const [field, direction] = rule.split(\":\");\n            const valA = a[field];\n            const valB = b[field];\n\n            if (valA === undefined || valB === undefined) continue;\n\n            const isAsc = direction === \"asc\";\n            const isDesc = direction === \"desc\";\n\n            if (!isAsc && !isDesc) {\n                console.warn(`Direção inválida: \"${direction}\". Use \"asc\" ou \"desc\".`);\n                continue;\n            }\n\n            if (valA < valB) return isAsc ? -1 : 1;\n            if (valA > valB) return isAsc ? 1 : -1;\n        }\n        return 0;\n    });\n}\n\n// ============================================\n// EXPORTS\n// ============================================\n\nexport default {\n\texpandArrayFieldToBoolean,\n\tsortFields\n};","/**\n * Search to URL Query Serializer - Sistema de URLs com query params visíveis\n * \n * Sistema de serialização para URLs de busca com todos os parâmetros visíveis\n * na query string, sem compactação ou ocultação em base64.\n * \n * FORMATO DE ENTRADA:\n * {\n *   \"filters\": {\n *     \"reference\": \"1829\",\n *     \"tipo\": \"Casa\"\n *   },\n *   \"search\": \"casa moderna\",\n *   \"page\": 1,\n *   \"limit\": 20,\n *   \"sort\": \"valor_venda:asc\"\n * }\n * \n * FORMATO URL:\n * ?q=casa+moderna&reference=1829&tipo=Casa&page=1&limit=20&sort=valor_venda:asc\n * \n * @module search-to-url-query-serializer\n */\n\n// ==========================================\n// 📋 INTERFACES E TIPOS PRINCIPAIS\n// ==========================================\n\n/**\n * Parâmetros de busca genéricos\n */\nexport interface SearchParams {\n  filters?: Record<string, any>;\n  search?: string;  // 🆕 Search separado de filters\n  page?: number;\n  limit?: number;\n  sort?: string | Record<string, string>; // Aceita tanto string quanto objeto\n}\n\n/**\n * Configuração de campos e operadores\n * v1.2.2: Removido defaults - agora usa padrões hardcoded\n */\nexport interface FieldConfig {\n  fieldMapping?: Record<string, string>; // Mapeamento de campos (ex: search_text → q)\n  overrides?: Record<string, {\n    operator?: string;        // Operador específico para o campo\n    caseSensitive?: boolean;  // true = case-sensitive, false = case-insensitive (padrão)\n  }>;\n}\n\n/**\n * Defaults configuráveis para parâmetros de busca\n */\nexport interface SearchDefaults {\n  page: number;              // Página padrão (ex: 1)\n  limit: number;             // Limite padrão (ex: 20)\n  sort: string | Record<string, string>; // Ordenação padrão como objeto (ex: { updated_at: \"desc\" })\n}\n\n/**\n * Configuração para o SearchUrlBuilder\n */\nexport interface SearchUrlBuilderConfig {\n  rootUrl: string;           // URL raiz (ex: '/imoveis/')\n  enableSlug?: boolean;      // Habilitar geração automática de slug (padrão: false)\n  slugConfig?: SeoSlugConfig; // Configurações para geração de slug\n  fieldConfig?: FieldConfig;  // Configuração de campos e operadores\n  defaults?: Partial<SearchDefaults>; // Defaults configuráveis para page/limit/sort\n}\n\n/**\n * Configuração para geração de slug SEO\n */\nexport interface SeoSlugConfig {\n  slugPrefix?: string;        // Prefixo para o slug (ex: \"imoveis\")\n  maxSlugLength?: number;     // Tamanho máximo do slug (padrão: 100)\n  requiredFields?: string[];  // Campos obrigatórios para gerar slug\n}\n\n/**\n * Estrutura interna do search_text nos filters\n * NOVA ARQUITETURA: search_text pode ser string simples ou objeto\n */\nexport interface SearchTextFilter {\n  search: string;\n}\n\n/**\n * Tipo unificado para search_text na nova arquitetura\n */\nexport type SearchTextValue = string | SearchTextFilter;\n\n/**\n * Resultado da construção de URL\n */\nexport interface BuildUrlResult {\n  url: string;           // URL completa\n  slug: string | null;   // Slug SEO gerado (ou null)\n  queryString: string;   // Query string com todos os parâmetros\n  hasSlug: boolean;      // Se slug foi gerado\n}\n\n// ==========================================\n// 🏗️ CLASSE PRINCIPAL - SEARCH URL BUILDER\n// ==========================================\n\nexport class SearchUrlBuilder {\n  private config: SearchUrlBuilderConfig;\n  private fieldMapping: Record<string, string>;\n  private defaults: SearchDefaults;\n\n  constructor(config: SearchUrlBuilderConfig) {\n    this.config = {\n      enableSlug: false,\n      fieldConfig: {\n        fieldMapping: {\n          search_text: \"q\"  // Mapeamento padrão\n        },\n        overrides: {}\n      },\n      ...config\n    };\n\n    // Garantir que rootUrl termina com '/'\n    if (!this.config.rootUrl.endsWith('/')) {\n      this.config.rootUrl += '/';\n    }\n\n    // Extrair fieldMapping para uso rápido\n    this.fieldMapping = this.config.fieldConfig?.fieldMapping || { search_text: \"q\" };\n    \n    // Configurar defaults (valores padrão configuráveis)\n    this.defaults = {\n      page: 1,\n      limit: 20,\n      sort: { updated_at: \"desc\" },  // ✅ OBJETO por padrão\n      ...this.config.defaults\n    };\n  }\n\n  // ==========================================\n  // 🔗 SERIALIZAÇÃO - Estado → URL\n  // ==========================================\n\n  /**\n   * Constrói URL de busca com query params visíveis\n   * \n   * @example\n   * ```typescript\n   * const builder = new SearchUrlBuilder({ rootUrl: '/imoveis/' });\n   * const result = builder.buildUrl({\n   *   filters: {\n   *     search_text: { search: \"casa moderna\" },\n   *     tipo: \"Casa\",\n   *     cidade: \"Ponta Grossa\"\n   *   },\n   *   page: 2\n   * });\n   * \n   * // result.url: \"/imoveis/?q=casa+moderna&tipo=Casa&cidade=Ponta+Grossa&page=2\"\n   * ```\n   */\n  public buildUrl(params: SearchParams): BuildUrlResult {\n    // 🏷️ Gerar slug SEO se habilitado\n    let slug: string | null = null;\n    if (this.config.enableSlug && params.filters) {\n      slug = this.generateSlugFromFilters(params.filters);\n    }\n\n    // 🔗 Construir query string MANUALMENTE (RFC 3986: : e [] não precisam encoding!)\n    const queryParts: string[] = [];\n\n    // 🆕 Adicionar search diretamente (SEM extractAndFlattenFilters)\n    if (params.search && params.search.trim()) {\n      const mappedField = this.fieldMapping.search_text || 'q';\n      const encodedValue = encodeURIComponent(params.search.trim()).replace(/%20/g, '+');\n      queryParts.push(`${mappedField}=${encodedValue}`);\n    }\n\n    // Adicionar todos os filtros diretamente\n    if (params.filters) {\n      Object.entries(params.filters).forEach(([key, value]) => {\n        const serializedValue = this.serializeComplexValue(value);\n        const encodedValue = encodeURIComponent(serializedValue).replace(/%20/g, '+');\n        queryParts.push(`${key}=${encodedValue}`);\n      });\n    }\n\n    // ✨ NOVA LÓGICA: Adicionar paginação e ordenação (apenas se diferente dos defaults)\n    if (params.page && params.page !== this.defaults.page) {\n      queryParts.push(`page=${params.page}`);\n    }\n    if (params.limit && params.limit !== this.defaults.limit) {\n      queryParts.push(`limit=${params.limit}`);\n    }\n    // Processar sort: { valor_venda: \"desc\" } → \"valor_venda_desc\"\n    if (params.sort) {\n      let sortString: string;\n      \n      if (typeof params.sort === 'string') {\n        // Já é string, usar diretamente\n        sortString = params.sort.trim();\n      } else if (typeof params.sort === 'object' && params.sort !== null) {\n        // É objeto: { valor_venda: \"desc\" } → \"valor_venda:desc\" (nova sintaxe)\n        const entries = Object.entries(params.sort);\n        if (entries.length === 1) {\n          const [field, direction] = entries[0];\n          sortString = `${field}:${direction}`;\n        } else {\n          // Se tiver múltiplos campos, usar o primeiro\n          const [field, direction] = entries[0];\n          sortString = `${field}:${direction}`;\n          console.warn('Sort com múltiplos campos, usando apenas o primeiro:', { field, direction });\n        }\n      } else {\n        sortString = String(params.sort);\n      }\n      \n      // ✨ NOVA LÓGICA: Adicionar sort apenas se diferente do default\n      if (sortString && sortString.trim()) {\n        // Converter default object para string para comparar\n        const defaultSortString = this.sortObjectToString(this.defaults.sort);\n        if (sortString.trim() !== defaultSortString) {\n          // 🎯 RFC 3986: : e [] não precisam encoding!\n          queryParts.push(`sort=${sortString.trim()}`);\n        }\n      }\n    }\n\n    const queryString = queryParts.join('&');\n\n    // 🔗 Construir URL final\n    let url = this.config.rootUrl.replace(/\\/$/, ''); // Remove / final temporário\n    if (slug) {\n      url += `/${slug}`;\n    }\n    if (queryString) {\n      url += `?${queryString}`;\n    }\n\n    return {\n      url,\n      slug,\n      queryString,\n      hasSlug: !!slug\n    };\n  }\n\n  // ==========================================\n  // 🔗 DESERIALIZAÇÃO - URL → Estado\n  // ==========================================\n\n  /**\n   * Extrai parâmetros de busca da URL (todos visíveis)\n   * \n   * @example\n   * ```typescript\n   * const builder = new SearchUrlBuilder({ rootUrl: '/imoveis/' });\n   * const params = builder.parseUrl(context);\n   * \n   * // Retorna exatamente o que estava na URL:\n   * // {\n   * //   filters: { search_text: { search: \"casa\" }, tipo: \"Casa\" },\n   * //   page: 2,\n   * //   limit: 25,\n   * //   sort: 'valor_venda_desc'\n   * // }\n   * ```\n   */\n  public parseUrl(context: any): SearchParams {\n    // 📥 Extrair query (ignorar slug)\n    const { slug, ...query } = context.query;\n    \n    // 🔍 Processar todos os parâmetros\n    const result: SearchParams = {};\n\n    // Extrair search_text usando fieldMapping (buscar por todos os valores mapeados)\n    let searchQuery: string | undefined;\n    const reverseMappingForSearchText = Object.entries(this.fieldMapping)\n      .find(([field]) => field === 'search_text')?.[1] || 'q';\n    \n    searchQuery = query[reverseMappingForSearchText];\n    delete query[reverseMappingForSearchText];\n\n    // Extrair paginação e ordenação\n    const page = query.page ? parseInt(query.page, 10) : undefined;\n    const limit = query.limit ? parseInt(query.limit, 10) : undefined;\n    \n    // Parse sort: \"valor_venda:asc\" → { valor_venda: \"asc\" } (nova sintaxe)\n    let sort: any = undefined;\n    if (query.sort && typeof query.sort === 'string') {\n      const sortMatch = query.sort.match(/^(.+):(asc|desc)$/);\n      if (sortMatch) {\n        const [, field, direction] = sortMatch;\n        sort = { [field]: direction };\n      } else {\n        // Backward compatibility: tentar formato antigo \"field_direction\"\n        const legacyMatch = query.sort.match(/^(.+)_(asc|desc)$/);\n        if (legacyMatch) {\n          const [, field, direction] = legacyMatch;\n          sort = { [field]: direction };\n        } else {\n          sort = query.sort; // Manter como string se não seguir padrão\n        }\n      }\n    }\n\n    delete query.page;\n    delete query.limit;\n    delete query.sort;\n\n    // 🔄 Reconstitui filters (SEM search_text/q)\n    const filters: Record<string, any> = {};\n\n    // Adicionar todos os outros filtros da query (com suporte a base64)\n    Object.entries(query).forEach(([key, value]) => {\n      filters[key] = this.parseComplexValue(value as string);\n    });\n\n    // ✨ NOVA LÓGICA: Montar resultado final\n    if (Object.keys(filters).length > 0) {\n      result.filters = filters;\n    }\n    \n    // 🆕 SEARCH SEPARADO (não vai para filters!)\n    if (searchQuery && searchQuery.trim()) {\n      result.search = searchQuery.trim();\n    }\n    \n    // Sempre aplicar defaults (mesmo que não venham da URL)\n    result.page = page || this.defaults.page;\n    result.limit = limit || this.defaults.limit;\n    result.sort = sort || this.defaults.sort;\n\n    return result;\n  }\n\n  // ==========================================\n  // 🚀 ENRIQUECIMENTO PARA FRONTEND REQUEST\n  // ==========================================\n\n  /**\n   * Enriquece estado Zustand para FrontendRequest (compatível com SearchRequestToPrismaMapper)\n   * \n   * @example\n   * ```typescript\n   * const builder = new SearchUrlBuilder({ rootUrl: '/imoveis/' });\n   * const enriched = builder.enrichForFrontendRequest(zustandState, {\n   *   fields: [\"reference\", \"title\"],\n   *   relations: { broker: [\"name\", \"phone\"] }\n   * });\n   * \n   * // enriched é compatível com SearchRequestToPrismaMapper\n   * const prismaQuery = mapSearchRequestToPrisma(enriched);\n   * ```\n   */\n  public enrichForFrontendRequest(\n    zustandState: SearchParams,\n    options?: {\n      fields?: string[];\n      relations?: Record<string, string[] | boolean>;\n    }\n  ): any {\n    const { fields, relations } = options || {};\n    const { filters = {}, page, limit, sort } = zustandState;\n\n    // 🔄 Converter filtros do Zustand para formato API com operadores\n    const enrichedFilters = this.enrichFiltersWithOperators(filters);\n\n    return {\n      filters: enrichedFilters,\n      ...(page && { page }),\n      ...(limit && { limit }),\n      ...(sort && { sort }),\n      ...(fields && { fields }),\n      ...(relations && { relations })\n    };\n  }\n\n  // ==========================================\n  // 🔧 MÉTODOS AUXILIARES PRIVADOS\n  // ==========================================\n\n  // Métodos extractAndFlattenFilters e addParamToUrl removidos (não eram utilizados)\n\n  /**\n   * Parse valores da URL, tentando detectar o tipo correto\n   */\n  private parseUrlValue(value: any): any {\n    if (!value) return value;\n\n    const stringValue = Array.isArray(value) ? value[0] : value;\n\n    // Tentar parse como número\n    if (/^\\d+$/.test(stringValue)) {\n      return parseInt(stringValue, 10);\n    }\n\n    // Tentar parse como boolean\n    if (stringValue === 'true') return true;\n    if (stringValue === 'false') return false;\n\n    // Tentar parse como JSON PRIMEIRO (antes de array CSV)\n    if (stringValue.startsWith('{') || stringValue.startsWith('[')) {\n      try {\n        return JSON.parse(stringValue);\n      } catch {\n        // Se falhar, continua para array CSV\n      }\n    }\n\n    // Tentar parse como array (separado por vírgula) - apenas se não é JSON\n    if (stringValue.includes(',') && !stringValue.startsWith('{') && !stringValue.startsWith('[')) {\n      return stringValue.split(',').map((item: string) => item.trim());\n    }\n\n    return stringValue;\n  }\n\n  /**\n   * Converte sort object para string para comparações\n   */\n  private sortObjectToString(sort: string | Record<string, string>): string {\n    if (typeof sort === 'string') {\n      return sort;\n    }\n    \n    if (typeof sort === 'object' && sort !== null) {\n      const entries = Object.entries(sort);\n      if (entries.length === 1) {\n        const [field, direction] = entries[0];\n        return `${field}:${direction}`;\n      }\n    }\n    \n    return '';\n  }\n\n  // ==========================================\n  // 🗜️ BASE64 PARA OBJETOS COMPLEXOS\n  // ==========================================\n\n  /**\n   * Verifica se valor é um objeto complexo que precisa de base64\n   */\n  private isComplexObject(value: any): boolean {\n    return typeof value === 'object' && \n           value !== null && \n           !Array.isArray(value) &&\n           Object.keys(value).length > 1;\n  }\n\n  /**\n   * Serializa valor complexo com base64 se necessário\n   */\n  private serializeComplexValue(value: any): string {\n    if (this.isComplexObject(value)) {\n      return 'base64:' + Buffer.from(JSON.stringify(value)).toString('base64');\n    }\n    return String(value);\n  }\n\n  /**\n   * Parse valor que pode ser base64 encoded\n   */\n  private parseComplexValue(value: string): any {\n    if (typeof value === 'string' && value.startsWith('base64:')) {\n      try {\n        const decoded = Buffer.from(value.substring(7), 'base64').toString();\n        return JSON.parse(decoded);\n      } catch (e) {\n        console.warn('Erro ao decodificar base64:', value);\n        return value;\n      }\n    }\n    return this.parseUrlValue(value);\n  }\n\n  /**\n   * Gera slug SEO baseado nos filtros (integração com seo-slug-generator)\n   */\n  private generateSlugFromFilters(filters: Record<string, any>): string | null {\n    // Importar dynamicamente para evitar dependência circular\n    try {\n      const { generateSeoSlugWithOptions } = require('../seo-slug-generator');\n      return generateSeoSlugWithOptions(filters, this.config.slugConfig);\n    } catch (error) {\n      console.warn('Erro ao gerar slug SEO:', error);\n      return null;\n    }\n  }\n\n  /**\n   * Enriquece filtros do Zustand com operadores para API\n   * v1.2.2: Usa lógica AND/OR ao invés de operadores Prisma específicos\n   * Padrões hardcoded: strings = equals, arrays = or\n   */\n  private enrichFiltersWithOperators(filters: Record<string, any>): Record<string, any> {\n    console.log('🔄 [enrichFiltersWithOperators] ENTRADA:', JSON.stringify(filters, null, 2));\n    \n    // 1. Primeiro processar ranges (_min/_max → gte/lte)\n    const rangeProcessed = this.processRangeFields(filters);\n    console.log('📊 [enrichFiltersWithOperators] Após processamento de ranges:', JSON.stringify(rangeProcessed, null, 2));\n    \n    const enriched: Record<string, any> = {};\n    const fieldConfig = this.config.fieldConfig!;\n    \n    // Padrões HARDCODED (v1.2.2)\n    const DEFAULT_STRING_OPERATOR = \"equals\";\n    const DEFAULT_ARRAY_OPERATOR = \"or\";\n\n    Object.entries(rangeProcessed).forEach(([key, value]) => {\n      if (value === null || value === undefined) return;\n\n      // Aplicar configuração específica do campo ou padrão hardcoded\n      const override = fieldConfig.overrides?.[key];\n      // v1.2.3: Case-insensitive por padrão, só enviar caseSensitive quando for true\n      const caseSensitive = override?.caseSensitive;\n\n      // Processamento específico por campo\n      if (key === 'search_text') {\n        // search_text sempre vira { search: \"...\" }\n        if (typeof value === 'string') {\n          enriched[key] = { search: value };\n          console.log(`🔍 [enrichFiltersWithOperators] search_text: ${JSON.stringify(enriched[key])}`);\n        } else if (typeof value === 'object' && value.search) {\n          enriched[key] = value; // Já está no formato correto\n        }\n      } else if (Array.isArray(value)) {\n        // Arrays: usar operador configurado ou padrão OR\n        const operator = override?.operator || DEFAULT_ARRAY_OPERATOR;\n        console.log(`📋 [enrichFiltersWithOperators] Array ${key}: operador=${operator}`);\n        \n        if (operator === 'and') {\n          enriched[key] = { and: value };\n        } else if (operator === 'or') {\n          enriched[key] = { or: value };\n        } else {\n          // Outros operadores específicos (não deveria acontecer com arrays)\n          enriched[key] = { [operator]: value };\n        }\n      } else if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || value === null) {\n        // Valores simples: aplicar operador configurado ou MANTER SIMPLES (equals implícito)\n        const operator = override?.operator || DEFAULT_STRING_OPERATOR;\n        console.log(`📝 [enrichFiltersWithOperators] ${typeof value} ${key}: operador=${operator}`);\n        \n        // v1.2.3: Equals implícito - valor direto quando operador é 'equals'\n        if (operator === 'equals' || !operator) {\n          enriched[key] = value;  // VALOR DIRETO = equals implícito\n        } \n        // Operadores que precisam de estrutura especial\n        else if (operator === 'contains') {\n          // Só adiciona caseSensitive se for true (false é padrão)\n          enriched[key] = caseSensitive \n            ? { contains: value, caseSensitive: true }\n            : { contains: value };\n        } else if (operator === 'startsWith') {\n          // Só adiciona caseSensitive se for true (false é padrão)\n          enriched[key] = caseSensitive\n            ? { startsWith: value, caseSensitive: true }\n            : { startsWith: value };\n        } else if (operator === 'endsWith') {\n          // Só adiciona caseSensitive se for true (false é padrão)\n          enriched[key] = caseSensitive\n            ? { endsWith: value, caseSensitive: true }\n            : { endsWith: value };\n        } else if (operator === 'search') {\n          enriched[key] = { search: value };\n        } else if (operator === 'not') {\n          enriched[key] = { not: value };\n        } else if (operator === 'gt') {\n          enriched[key] = { gt: value };\n        } else if (operator === 'gte') {\n          enriched[key] = { gte: value };\n        } else if (operator === 'lt') {\n          enriched[key] = { lt: value };\n        } else if (operator === 'lte') {\n          enriched[key] = { lte: value };\n        } else {\n          // Operador desconhecido, manter valor simples\n          enriched[key] = value;\n        }\n      } else if (typeof value === 'object' && !Array.isArray(value)) {\n        // Objetos: verificar se já tem operadores ou se é range\n        if (this.hasOperators(value)) {\n          enriched[key] = value; // Já tem operadores\n          console.log(`🔧 [enrichFiltersWithOperators] Objeto com operadores mantido: ${key} = ${JSON.stringify(enriched[key])}`);\n        } else {\n          enriched[key] = value; // Manter como está\n          console.log(`📦 [enrichFiltersWithOperators] Objeto simples mantido: ${key} = ${JSON.stringify(enriched[key])}`);\n        }\n      } else {\n        // Outros tipos: manter como está\n        enriched[key] = value;\n        console.log(`💎 [enrichFiltersWithOperators] Outro tipo mantido: ${key} = ${JSON.stringify(enriched[key])}`);\n      }\n    });\n\n    console.log('✅ [enrichFiltersWithOperators] SAÍDA:', JSON.stringify(enriched, null, 2));\n    return enriched;\n  }\n\n  /**\n   * Verifica se um objeto já contém operadores\n   * v1.2.2: Inclui operadores lógicos AND/OR\n   */\n  private hasOperators(obj: any): boolean {\n    const operators = [\n      // Operadores lógicos (v1.2.2)\n      'and', 'or',\n      // Operadores de comparação\n      'equals', 'not', 'gt', 'gte', 'lt', 'lte',\n      // Operadores de texto\n      'contains', 'startsWith', 'endsWith', 'search',\n      // Operadores legacy (ainda suportados para compatibilidade)\n      'in', 'notIn', 'has', 'hasSome', 'hasEvery'\n    ];\n    return Object.keys(obj).some(key => operators.includes(key));\n  }\n\n  /**\n   * Processa ranges automáticos no nível principal dos filtros\n   * Identifica campos com _min/_max e os converte para operadores gte/lte\n   */\n  private processRangeFields(filters: Record<string, any>): Record<string, any> {\n    console.log('📊 [processRangeFields] ENTRADA:', JSON.stringify(filters, null, 2));\n    \n    const processed: Record<string, any> = {};\n    const rangeFields: Record<string, { min?: any, max?: any }> = {};\n\n    // 1. Identificar e agrupar campos range\n    Object.entries(filters).forEach(([key, value]) => {\n      if (key.endsWith('_min')) {\n        const baseField = key.replace('_min', '');\n        if (!rangeFields[baseField]) rangeFields[baseField] = {};\n        rangeFields[baseField].min = value;\n        console.log(`📈 [processRangeFields] Range min encontrado: ${baseField}_min = ${value}`);\n      } else if (key.endsWith('_max')) {\n        const baseField = key.replace('_max', '');\n        if (!rangeFields[baseField]) rangeFields[baseField] = {};\n        rangeFields[baseField].max = value;\n        console.log(`📉 [processRangeFields] Range max encontrado: ${baseField}_max = ${value}`);\n      } else {\n        // Campo normal, manter como está\n        processed[key] = value;\n      }\n    });\n\n    // 2. Converter ranges para operadores gte/lte\n    Object.entries(rangeFields).forEach(([baseField, range]) => {\n      const rangeOperator: Record<string, any> = {};\n      \n      if (range.min !== undefined && range.min !== null) {\n        rangeOperator.gte = range.min;\n        console.log(`⬆️ [processRangeFields] Adicionando gte: ${baseField}.gte = ${range.min}`);\n      }\n      \n      if (range.max !== undefined && range.max !== null) {\n        rangeOperator.lte = range.max;\n        console.log(`⬇️ [processRangeFields] Adicionando lte: ${baseField}.lte = ${range.max}`);\n      }\n      \n      // Só adicionar se tiver pelo menos um operador\n      if (Object.keys(rangeOperator).length > 0) {\n        processed[baseField] = rangeOperator;\n        console.log(`✅ [processRangeFields] Range convertido: ${baseField} = ${JSON.stringify(rangeOperator)}`);\n      }\n    });\n\n    console.log('✅ [processRangeFields] SAÍDA:', JSON.stringify(processed, null, 2));\n    return processed;\n  }\n}\n\n// ==========================================\n// 🧪 FUNÇÕES DE UTILIDADE E TESTE\n// ==========================================\n\n/**\n * Cria SearchParams para testes\n */\nexport function createSearchParams(\n  filters?: Record<string, any>,\n  page?: number,\n  limit?: number,\n  sort?: string\n): SearchParams {\n  const params: SearchParams = {};\n  \n  if (filters) params.filters = filters;\n  if (page) params.page = page;\n  if (limit) params.limit = limit;\n  if (sort) params.sort = sort;\n  \n  return params;\n}\n\n/**\n * Valida se um objeto é um SearchParams válido\n */\nexport function validateSearchParams(params: any): params is SearchParams {\n  if (!params || typeof params !== 'object') return false;\n  \n  // filters deve ser object ou undefined\n  if (params.filters !== undefined && typeof params.filters !== 'object') return false;\n  \n  // page deve ser number ou undefined\n  if (params.page !== undefined && (typeof params.page !== 'number' || params.page < 1)) return false;\n  \n  // limit deve ser number ou undefined\n  if (params.limit !== undefined && (typeof params.limit !== 'number' || params.limit < 1)) return false;\n  \n  // sort deve ser string ou undefined\n  if (params.sort !== undefined && typeof params.sort !== 'string') return false;\n  \n  return true;\n}\n\n/**\n * Valida se filters contém uma estrutura search_text válida\n * NOVA ARQUITETURA: aceita string simples ou objeto { search: \"...\" }\n */\nexport function validateSearchTextFilter(searchText: any): searchText is SearchTextValue {\n  if (!searchText) return false;\n  \n  // Formato NOVO: string simples\n  if (typeof searchText === 'string') return true;\n  \n  // Formato ANTIGO: objeto { search: \"...\" }\n  if (typeof searchText === 'object' && typeof searchText.search === 'string') return true;\n  \n  return false;\n}\n\n/**\n * Testa round-trip (serializar → deserializar → comparar)\n */\nexport function testSearchRoundTrip(params: SearchParams, config: SearchUrlBuilderConfig): {\n  success: boolean;\n  original: SearchParams;\n  result: SearchParams;\n  url: string;\n  buildResult: BuildUrlResult;\n} {\n  const builder = new SearchUrlBuilder(config);\n  const buildResult = builder.buildUrl(params);\n  \n  // Converter URLSearchParams entries para objeto\n  const queryObject: Record<string, any> = {};\n  new URLSearchParams(buildResult.queryString).forEach((value, key) => {\n    queryObject[key] = value;\n  });\n  \n  const mockContextFormatted = { query: queryObject };\n  const result = builder.parseUrl(mockContextFormatted);\n  \n  return {\n    success: JSON.stringify(params) === JSON.stringify(result),\n    original: params,\n    result,\n    url: buildResult.url,\n    buildResult\n  };\n}","/**\n * 🔧 Filter Helpers - Utilitários Compartilhados\n * \n * Funções auxiliares para conversão e validação de filtros\n * RESPONSABILIDADES:\n * - Conversões de formato (camelCase ↔ snake_case)\n * - Validações de tipos e estruturas\n * - Coleta de parâmetros SQL\n * - Cálculos de complexidade\n * - Normalização de dados\n */\n\nimport type { HorizonSchema, HorizonField, GeospatialFilter } from './interfaces'\n\n// ==========================================\n// 🔄 CONVERSÕES DE FORMATO\n// ==========================================\n\n/**\n * Converte camelCase para snake_case\n */\nexport function toSnakeCase(str: string): string {\n  return str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`)\n}\n\n/**\n * Converte snake_case para camelCase\n */\nexport function toCamelCase(str: string): string {\n  return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase())\n}\n\n/**\n * Normaliza nome de coluna do banco baseado no schema\n */\nexport function getDbColumnName(fieldName: string, fieldInfo?: HorizonField): string {\n  return (typeof fieldInfo?.db === 'string' ? fieldInfo.db : toSnakeCase(fieldName))\n}\n\n// ==========================================\n// 🧪 VALIDAÇÕES DE TIPOS\n// ==========================================\n\n/**\n * Verifica se é um valor simples (string, number, boolean)\n */\nexport function isSimpleValue(value: any): boolean {\n  return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'\n}\n\n/**\n * Verifica se o campo é array baseado no schema\n */\nexport function isArrayField(fieldType?: string): boolean {\n  return fieldType?.endsWith('[]') || false\n}\n\n/**\n * Verifica se é um filtro de fulltext search\n */\nexport function isFulltextFilter(value: any): boolean {\n  return value && typeof value === 'object' && 'search' in value\n}\n\n/**\n * Verifica se é um filtro geoespacial\n */\nexport function isGeospatialFilter(value: any): boolean {\n  if (!value || typeof value !== 'object') return false\n  \n  return (\n    'type' in value ||           // Structured format: { type: 'bbox', bounds: ... }\n    'bounds' in value ||         // Legacy: { bounds: ... }\n    'polygon' in value ||        // Legacy: { polygon: ... }\n    'point' in value             // Legacy: { point: ... }\n  )\n}\n\n/**\n * Verifica se é um filtro de array (OR/AND operators)\n */\nexport function isArrayFilter(value: any): boolean {\n  return value && typeof value === 'object' && ('or' in value || 'and' in value)\n}\n\n/**\n * Verifica se há filtros de range\n */\nexport function hasRangeOperators(value: any): boolean {\n  return value && typeof value === 'object' && \n    (value.gte !== undefined || value.gt !== undefined || \n     value.lte !== undefined || value.lt !== undefined ||\n     value.between !== undefined)\n}\n\n/**\n * Verifica se há operadores EXISTS/NOT EXISTS\n */\nexport function hasExistsOperators(value: any): boolean {\n  return value && typeof value === 'object' && 'exists' in value\n}\n\n// ==========================================\n// 🗄️ SCHEMA UTILITIES\n// ==========================================\n\n/**\n * Cria mapa de campos do schema para acesso rápido\n */\nexport function createSchemaFieldMap(schema?: HorizonSchema): Map<string, HorizonField> {\n  const map = new Map<string, HorizonField>()\n  \n  if (schema?.fields) {\n    schema.fields.forEach(field => {\n      map.set(field.name, field)\n    })\n  }\n  \n  return map\n}\n\n/**\n * Obtém informações do campo do schema\n */\nexport function getFieldInfo(fieldName: string, schemaMap: Map<string, HorizonField>): HorizonField | undefined {\n  return schemaMap.get(fieldName)\n}\n\n/**\n * Obtém tipo do campo (com fallback para 'string')\n */\nexport function getFieldType(fieldName: string, schemaMap: Map<string, HorizonField>): string {\n  return getFieldInfo(fieldName, schemaMap)?.type || 'string'\n}\n\n// ==========================================\n// 📊 CÁLCULOS E ANÁLISES\n// ==========================================\n\n/**\n * Calcula complexidade da query baseado nos filtros\n */\nexport function calculateComplexity(\n  filterCount: number,\n  hasFulltext: boolean,\n  hasGeo: boolean,\n  hasArrays: boolean,\n  hasRanges: boolean\n): number {\n  let complexity = filterCount\n\n  // Diferentes tipos de filtros adicionam complexidade\n  if (hasFulltext) complexity += 2\n  if (hasGeo) complexity += 3\n  if (hasArrays) complexity += 1\n  if (hasRanges) complexity += 0.5\n\n  return Math.round(complexity * 10) / 10\n}\n\n/**\n * Analisa filtros e retorna estatísticas\n */\nexport function analyzeFilters(filters: Record<string, any>): {\n  hasFulltext: boolean\n  hasGeo: boolean\n  hasArrays: boolean\n  hasRanges: boolean\n  hasExists: boolean\n  filterCount: number\n  complexity: number\n} {\n  const filterEntries = Object.entries(filters)\n  const analysis = {\n    hasFulltext: false,\n    hasGeo: false,\n    hasArrays: false,\n    hasRanges: false,\n    hasExists: false,\n    filterCount: filterEntries.length,\n    complexity: 0\n  }\n\n  filterEntries.forEach(([, value]) => {\n    if (isFulltextFilter(value)) analysis.hasFulltext = true\n    if (isGeospatialFilter(value)) analysis.hasGeo = true\n    if (isArrayFilter(value)) analysis.hasArrays = true\n    if (hasRangeOperators(value)) analysis.hasRanges = true\n    if (hasExistsOperators(value)) analysis.hasExists = true\n  })\n\n  analysis.complexity = calculateComplexity(\n    analysis.filterCount,\n    analysis.hasFulltext,\n    analysis.hasGeo,\n    analysis.hasArrays,\n    analysis.hasRanges\n  )\n\n  return analysis\n}\n\n// ==========================================\n// 🔧 COLETA DE PARÂMETROS\n// ==========================================\n\n/**\n * Coleta parâmetros para binding SQL de um filtro específico\n */\nexport function collectFilterParameters(key: string, value: any): Record<string, any> {\n  const params: Record<string, any> = {}\n\n  // Pular valores null (tratados como IS NULL)\n  if (value === null) {\n    return params\n  }\n\n  // Valor simples\n  if (isSimpleValue(value)) {\n    params[key] = value\n    return params\n  }\n\n  // Objeto com propriedades específicas\n  if (value && typeof value === 'object') {\n    // Fulltext search\n    if (value.search) {\n      params[`${key}_search`] = value.search\n    }\n\n    // Array operators\n    if (value.or) {\n      params[`${key}_or`] = value.or\n    }\n    if (value.and) {\n      params[`${key}_and`] = value.and\n    }\n\n    // Range operators\n    if (value.gte !== undefined) params[`${key}_gte`] = value.gte\n    if (value.gt !== undefined) params[`${key}_gt`] = value.gt\n    if (value.lte !== undefined) params[`${key}_lte`] = value.lte\n    if (value.lt !== undefined) params[`${key}_lt`] = value.lt\n    \n    // Between operator\n    if (value.between && Array.isArray(value.between) && value.between.length === 2) {\n      params[`${key}_between_start`] = value.between[0]\n      params[`${key}_between_end`] = value.between[1]\n    }\n  }\n\n  return params\n}\n\n/**\n * Coleta parâmetros geoespaciais\n */\nexport function collectGeoParameters(geoFilter?: GeospatialFilter | null): Record<string, any> {\n  const params: Record<string, any> = {}\n\n  if (geoFilter && 'polygon' in geoFilter) {\n    params.polygon = (geoFilter as any).polygon\n  }\n\n  return params\n}\n\n/**\n * Coleta todos os parâmetros de um conjunto de filtros\n */\nexport function collectAllParameters(\n  filters: Record<string, any>, \n  geoFilter?: GeospatialFilter | null\n): Record<string, any> {\n  const params: Record<string, any> = {}\n\n  // Parâmetros de filtros normais\n  Object.entries(filters).forEach(([key, value]) => {\n    Object.assign(params, collectFilterParameters(key, value))\n  })\n\n  // Parâmetros geoespaciais\n  Object.assign(params, collectGeoParameters(geoFilter))\n\n  return params\n}\n\n// ==========================================\n// 📝 NORMALIZAÇÃO DE DADOS\n// ==========================================\n\n/**\n * Normaliza texto de busca para fulltext search\n */\nexport function normalizeSearchText(searchText: string): string {\n  return searchText\n    .trim()\n    .replace(/\\s+/g, ' ')           // Múltiplos espaços → espaço único\n    .replace(/[^\\w\\sáéíóúâêîôûàèìòùãõç-]/gi, '') // Remove caracteres especiais\n    .toLowerCase()\n}\n\n/**\n * Valida bounds geográficos\n */\nexport function validateGeoBounds(bounds: any): boolean {\n  if (!bounds || typeof bounds !== 'object') return false\n  \n  const { north, south, east, west } = bounds\n  \n  return (\n    typeof north === 'number' &&\n    typeof south === 'number' &&\n    typeof east === 'number' &&\n    typeof west === 'number' &&\n    north > south &&\n    east > west\n  )\n}\n\n/**\n * Valida estrutura de filtro geoespacial\n */\nexport function validateGeoFilter(geoFilter: any): boolean {\n  if (!geoFilter || typeof geoFilter !== 'object') return false\n\n  // BBOX validation\n  if (geoFilter.bounds) {\n    return validateGeoBounds(geoFilter.bounds)\n  }\n\n  // Polygon validation\n  if (geoFilter.polygon) {\n    return typeof geoFilter.polygon === 'string' && geoFilter.polygon.length > 0\n  }\n\n  // Point validation\n  if (geoFilter.point) {\n    const { lat, lng, radius } = geoFilter.point\n    return (\n      typeof lat === 'number' &&\n      typeof lng === 'number' &&\n      lat >= -90 && lat <= 90 &&\n      lng >= -180 && lng <= 180 &&\n      (radius === undefined || (typeof radius === 'number' && radius > 0))\n    )\n  }\n\n  return false\n}\n\n// ==========================================\n// 🔍 DEBUG E LOGGING\n// ==========================================\n\n/**\n * Gera informações de debug para um filtro\n */\nexport function getFilterDebugInfo(key: string, value: any, schemaMap: Map<string, HorizonField>): {\n  fieldName: string\n  dbColumn: string\n  fieldType: string\n  filterType: string\n  complexity: number\n} {\n  const fieldInfo = getFieldInfo(key, schemaMap)\n  \n  let filterType = 'simple'\n  let complexity = 1\n\n  if (isFulltextFilter(value)) {\n    filterType = 'fulltext'\n    complexity = 2\n  } else if (isGeospatialFilter(value)) {\n    filterType = 'geospatial'\n    complexity = 3\n  } else if (isArrayFilter(value)) {\n    filterType = 'array'\n    complexity = 1.5\n  } else if (hasRangeOperators(value)) {\n    filterType = 'range'\n    complexity = 1.2\n  } else if (hasExistsOperators(value)) {\n    filterType = 'exists'\n    complexity = 0.5\n  }\n\n  return {\n    fieldName: key,\n    dbColumn: getDbColumnName(key, fieldInfo),\n    fieldType: getFieldType(key, schemaMap),\n    filterType,\n    complexity\n  }\n}\n\n/**\n * Valida estrutura básica de filtros\n */\nexport function validateFiltersStructure(filters: any): { valid: boolean; errors: string[] } {\n  const errors: string[] = []\n\n  if (!filters) {\n    errors.push('Filters object is required')\n    return { valid: false, errors }\n  }\n\n  if (typeof filters !== 'object') {\n    errors.push('Filters must be an object')\n    return { valid: false, errors }\n  }\n\n  // Validar cada filtro\n  Object.entries(filters).forEach(([key, value]) => {\n    if (typeof key !== 'string' || key.length === 0) {\n      errors.push(`Invalid filter key: ${key}`)\n    }\n\n    // Validações específicas por tipo\n    if (isGeospatialFilter(value) && !validateGeoFilter(value)) {\n      errors.push(`Invalid geospatial filter for ${key}`)\n    }\n  })\n\n  return { valid: errors.length === 0, errors }\n}","/**\n * 🔄 Schema Adapter - Converte schemas para HorizonSchema\n * \n * Adapta schemas de diferentes formatos para o formato esperado pelo Filter Engine\n */\n\nimport type { HorizonSchema, HorizonField, HorizonFieldDb } from './interfaces'\n\n// ==========================================\n// 🚨 ADAPTER TEMPORÁRIO - INCONSISTÊNCIA DE SCHEMA\n// ==========================================\n\n/**\n * 🚨 ADAPTER TEMPORÁRIO PARA SCHEMA INCONSISTENCY\n * \n * PROBLEMA: JsonToZodGenerator usa formato {key, type: \"Number\"} (correto SSOT)\n *           mas HorizonField interface usa {name, type: \"string\"} (incorreto)\n * \n * SOLUÇÃO TEMPORÁRIA: Converter formato SSOT para formato esperado pelo Filter Engine\n * \n * TODO FUTURO: Remover este adapter e atualizar HorizonField interface para usar\n *              o formato SSOT diretamente: {key, type: \"Number\"}\n * \n * QUANDO REMOVER: Quando tivermos tempo de refatorar todos os 50+ arquivos que\n *                 dependem da interface HorizonField (testes, examples, docs, etc)\n */\nexport function convertToHorizonFormat(ssotSchema: any): HorizonSchema {\n  return {\n    entity: 'property', // TODO: tornar dinâmico se necessário\n    table: 'property',  // TODO: tornar dinâmico se necessário\n    pk: 'id',          // TODO: tornar dinâmico se necessário\n    fields: ssotSchema.fields.map((field: any) => convertFieldToHorizonFormat(field))\n  }\n}\n\n/**\n * 🚨 CONVERTE CAMPO SSOT PARA FORMATO HORIZON (TEMPORÁRIO)\n * \n * SSOT Format:     {key: \"id\", type: \"Number\"}     ← CORRETO\n * Horizon Format:  {name: \"id\", type: \"Number\"}    ← MANTER UPPERCASE AGORA!\n */\nfunction convertFieldToHorizonFormat(ssotField: any): HorizonField {\n  const horizonField: HorizonField = {\n    name: ssotField.key,                    // key → name\n    type: ssotField.type,                   // MANTER UPPERCASE: \"String[]\" não \"string[]\"\n    searchable: ssotField.searchable || false,  // Usar searchable se existe, não categories\n    \n    // DB mapping inteligente\n    db: convertDbConfig(ssotField),\n    \n    // Inferir facetable baseado no tipo\n    facetable: inferFacetable(ssotField),\n    \n    // Join é undefined para campos normais (só em casos específicos)\n    join: undefined\n  }\n\n  // PRESERVAR TODOS metadados do SSOT (mesmo que não use agora)\n  ;(horizonField as any)._ssotMetadata = {\n    label: ssotField.label,\n    categories: ssotField.categories,\n    format: ssotField.format,\n    unit: ssotField.unit,\n    validation: ssotField.validation,\n    conditions: ssotField.conditions,\n    parent: ssotField.parent,\n    description: ssotField.description,\n    origin: ssotField.origin\n  }\n\n  return horizonField\n}\n\n/**\n * 🔧 CONVERTE CONFIG DB DO SSOT PARA HORIZON FORMAT\n */\nfunction convertDbConfig(ssotField: any): string | HorizonFieldDb {\n  // REGRA 1: Se não tem db → usar key como coluna (90% dos casos)\n  if (!ssotField.db) {\n    return ssotField.key  // endereco_cidade → coluna \"endereco_cidade\"\n  }\n  \n  // REGRA 2: Se db é string → usar como coluna customizada (9% dos casos)  \n  if (typeof ssotField.db === 'string') {\n    return ssotField.db  // db: \"cidade\" → coluna \"cidade\"\n  }\n  \n  // REGRA 3: Se db é objeto → key continua sendo coluna + metadados extras (1% dos casos)\n  const dbConfig: HorizonFieldDb = {\n    column: ssotField.key  // ← SEMPRE usar key como coluna\n  }\n  \n  // Preservar metadados especiais\n  if (ssotField.db.fulltext_type) {\n    dbConfig.fulltext_type = ssotField.db.fulltext_type\n  }\n  \n  return dbConfig\n}\n\n/**\n * 📊 INFERE FACETABLE BASEADO NO TIPO DO CAMPO\n */\nfunction inferFacetable(ssotField: any): HorizonField['facetable'] {\n  // Se já tem facetable explícito, usar\n  if (ssotField.facetable !== undefined) {\n    return ssotField.facetable\n  }\n  \n  // Inferir baseado no tipo\n  const type = ssotField.type.toLowerCase()\n  \n  if (type === 'string' || type.startsWith('string')) {\n    return { enabled: true, kind: 'terms' }\n  }\n  if (type === 'number') {\n    return { enabled: true, kind: 'histogram' }\n  }\n  if (type === 'boolean') {\n    return { enabled: true, kind: 'terms' }\n  }\n  if (type.includes('date')) {\n    return { enabled: true, kind: 'date_histogram' }\n  }\n  \n  // Default para tipos desconhecidos\n  return { enabled: true, kind: 'terms' }\n}\n\n/**\n * Converte schema do Jetimob para formato HorizonSchema\n */\nexport function convertJetimobSchemaToHorizon(jetimobSchema: any): HorizonSchema {\n  return {\n    entity: 'property',\n    table: 'property',\n    pk: 'id',\n    fields: jetimobSchema.fields.map((field: any) => convertField(field))\n  }\n}\n\n/**\n * Converte campo individual do schema Jetimob\n */\nfunction convertField(jetimobField: any): HorizonField {\n  const horizonField: HorizonField = {\n    name: jetimobField.key,\n    type: jetimobField.type,\n    searchable: jetimobField.categories?.includes('search') || false\n  }\n\n  // Converter configuração do banco\n  if (jetimobField.db) {\n    if (typeof jetimobField.db === 'string') {\n      horizonField.db = jetimobField.db\n    } else {\n      const dbConfig: HorizonFieldDb = {\n        column: jetimobField.key // Usar key como padrão\n      }\n      \n      // Marcar campos fulltext especiais\n      if (jetimobField.db.fulltext_type) {\n        dbConfig.fulltext_type = jetimobField.db.fulltext_type\n      }\n      \n      horizonField.db = dbConfig\n    }\n  } else {\n    // Usar key como coluna padrão\n    horizonField.db = jetimobField.key\n  }\n\n  return horizonField\n}\n\n/**\n * Cria schema simplificado para testes\n */\nexport function createTestPropertySchema(): HorizonSchema {\n  return {\n    entity: 'property',\n    table: 'property',\n    pk: 'id',\n    fields: [\n      // Campos fulltext\n      {\n        name: 'fulltext',\n        type: 'string',\n        db: { column: 'fulltext', fulltext_type: 'text' }\n      },\n      {\n        name: 'fulltext_vector',\n        type: 'tsvector',\n        db: { column: 'fulltext_vector', fulltext_type: 'vector' }\n      },\n      \n      // Arrays PostgreSQL\n      {\n        name: 'operacao',\n        type: 'string[]',\n        db: 'operacao'\n      },\n      {\n        name: 'caracteristicas',\n        type: 'string[]',\n        db: 'caracteristicas'\n      },\n      \n      // Campos simples\n      {\n        name: 'tipo',\n        type: 'string',\n        db: 'tipo'\n      },\n      {\n        name: 'endereco_cidade',\n        type: 'string',\n        db: 'endereco_cidade'\n      },\n      {\n        name: 'endereco_bairro',\n        type: 'string',\n        db: 'endereco_bairro'\n      },\n      \n      // Campos numéricos\n      {\n        name: 'valor_venda',\n        type: 'number',\n        db: 'valor_venda'\n      },\n      {\n        name: 'area_total',\n        type: 'number',\n        db: 'area_total'\n      },\n      {\n        name: 'dormitorios',\n        type: 'number',\n        db: 'dormitorios'\n      },\n      \n      // Campo geoespacial\n      {\n        name: 'location',\n        type: 'geography',\n        db: 'location'\n      }\n    ]\n  }\n}","/**\n * 🌍 Geospatial Processor - Filter Engine\n * \n * Especializado em filtros geoespaciais com PostGIS\n * RESPONSABILIDADES:\n * - BBOX (bounding box) queries\n * - Polygon (WKT) queries  \n * - Radius (point + distance) queries\n * - PostGIS ST_* functions\n */\n\nimport type { \n  HorizonField,\n  FilterProcessor, \n  GeospatialFilter,\n  GeospatialResult,\n  Geometry\n} from '../interfaces'\n\n// ==========================================\n// 🎯 GEOSPATIAL PROCESSOR\n// ==========================================\n\nexport class GeospatialProcessor implements FilterProcessor {\n  name = 'geospatial'\n\n  /**\n   * Verifica se pode processar este filtro\n   */\n  canProcess(_key: string, value: any, _fieldInfo?: HorizonField): boolean {\n    if (!value || typeof value !== 'object') {\n      return false\n    }\n\n    // 🎯 NOVA ESTRUTURA: operation + geometry\n    return this.isNewGeospatialFilter(value)\n  }\n\n  /**\n   * Detecta nova estrutura geoespacial (operation + geometry)\n   */\n  private isNewGeospatialFilter(value: any): boolean {\n    return !!(value.operation && \n              value.geometry && \n              typeof value.geometry === 'object' &&\n              this.isValidOperation(value.operation) &&\n              this.isValidGeometry(value.geometry))\n  }\n\n  /**\n   * Valida operação espacial\n   */\n  private isValidOperation(operation: any): boolean {\n    return ['within', 'intersects', 'contains', 'near'].includes(operation)\n  }\n\n  /**\n   * Valida geometria\n   */\n  private isValidGeometry(geometry: any): boolean {\n    return geometry.type && ['bbox', 'polygon', 'point', 'circle'].includes(geometry.type)\n  }\n\n  /**\n   * Processa filtro geoespacial e retorna SQL + params\n   */\n  process(_key: string, value: any, _fieldInfo?: HorizonField, options?: { locationColumn?: string }): GeospatialResult {\n    // Determinar coluna de localização\n    const locationColumn = options?.locationColumn || 'location'\n    \n    // Validar que é nova estrutura\n    if (!this.isNewGeospatialFilter(value)) {\n      throw new Error(`Invalid geospatial filter format. Expected { operation, geometry }, got: ${JSON.stringify(value)}`)\n    }\n    \n    let geoFilter = value as GeospatialFilter\n    \n    // 🔧 GARANTIR distância padrão para operação 'near'\n    if (geoFilter.operation === 'near' && !geoFilter.distance) {\n      geoFilter = { ...geoFilter, distance: 1000 }\n    }\n    \n    // Gerar SQL baseado na operação e geometria\n    const sqlResult = this.generateGeoSQL(geoFilter, locationColumn)\n    \n    // Coletar parâmetros\n    const params = this.collectGeoParams(geoFilter)\n\n    return {\n      where: sqlResult.where,\n      params,\n      metadata: {\n        processorType: 'geospatial',\n        complexity: this.calculateGeoComplexity(geoFilter),\n        operation: geoFilter.operation,\n        geometryType: geoFilter.geometry.type,\n        usesPostGIS: true,\n        distance: geoFilter.distance,\n        hasSpecialFeatures: geoFilter.operation === 'near' || geoFilter.geometry.type === 'polygon'\n      }\n    }\n  }\n\n  /**\n   * Retorna fragmentos SQL suportados\n   */\n  getSupportedFragments(): string[] {\n    return [\n      'ST_Intersects_bbox',\n      'ST_Within_polygon', \n      'ST_DWithin_radius',\n      'ST_MakeEnvelope',\n      'ST_GeomFromText'\n    ]\n  }\n\n  // ==========================================\n  // 🔧 MÉTODOS PRIVADOS\n  // ==========================================\n\n  /**\n   * Gera SQL PostGIS baseado na operação e geometria\n   */\n  private generateGeoSQL(geoFilter: GeospatialFilter, locationColumn: string): { where: string } {\n    const { operation, geometry } = geoFilter\n\n    // Switch por operação espacial\n    switch (operation) {\n      case 'within':\n        return this.generateWithinSQL(geometry, locationColumn)\n      \n      case 'intersects':\n        return this.generateIntersectsSQL(geometry, locationColumn)\n      \n      case 'contains':\n        return this.generateContainsSQL(geometry, locationColumn)\n      \n      case 'near':\n        return this.generateNearSQL(geometry, locationColumn, geoFilter.distance || 1000)\n      \n      default:\n        throw new Error(`Unsupported geospatial operation: ${operation}`)\n    }\n  }\n\n  // ==========================================\n  // 🎯 OPERAÇÕES ESPACIAIS (4 operações principais)\n  // ==========================================\n\n  /**\n   * WITHIN: Encontrar geometrias DENTRO de uma área\n   * Usa: ST_Within(location, area)\n   */\n  private generateWithinSQL(geometry: Geometry, locationColumn: string): { where: string } {\n    switch (geometry.type) {\n      case 'bbox':\n        return this.generateWithinBboxSQL(geometry, locationColumn)\n      case 'polygon':\n        return this.generateWithinPolygonSQL(locationColumn)\n      case 'circle':\n        return this.generateWithinCircleSQL(geometry, locationColumn)\n      default:\n        throw new Error(`WITHIN operation not supported for geometry type: ${geometry.type}`)\n    }\n  }\n\n  /**\n   * INTERSECTS: Encontrar geometrias que INTERSECTAM com área\n   * Usa: ST_Intersects(location, area)\n   */\n  private generateIntersectsSQL(geometry: Geometry, locationColumn: string): { where: string } {\n    switch (geometry.type) {\n      case 'bbox':\n        return this.generateIntersectsBboxSQL(geometry, locationColumn)\n      case 'polygon':\n        return this.generateIntersectsPolygonSQL(locationColumn)\n      case 'circle':\n        return this.generateIntersectsCircleSQL(geometry, locationColumn)\n      default:\n        throw new Error(`INTERSECTS operation not supported for geometry type: ${geometry.type}`)\n    }\n  }\n\n  /**\n   * CONTAINS: Encontrar áreas que CONTÊM um ponto\n   * Usa: ST_Contains(area, point)\n   */\n  private generateContainsSQL(geometry: Geometry, locationColumn: string): { where: string } {\n    if (geometry.type !== 'point') {\n      throw new Error(`CONTAINS operation only supports 'point' geometry, got: ${geometry.type}`)\n    }\n    return this.generateContainsPointSQL(geometry, locationColumn)\n  }\n\n  /**\n   * NEAR: Encontrar geometrias PRÓXIMAS a um ponto\n   * Usa: ST_DWithin(location, point, distance)\n   */\n  private generateNearSQL(geometry: Geometry, locationColumn: string, distance: number): { where: string } {\n    if (geometry.type !== 'point') {\n      throw new Error(`NEAR operation only supports 'point' geometry, got: ${geometry.type}`)\n    }\n    return this.generateNearPointSQL(geometry, locationColumn, distance)\n  }\n\n  // ==========================================\n  // 🔧 IMPLEMENTAÇÕES ESPECÍFICAS POR GEOMETRIA\n  // ==========================================\n\n  /**\n   * WITHIN + BBOX: pontos dentro de bounding box\n   */\n  private generateWithinBboxSQL(geometry: any, locationColumn: string): { where: string } {\n    const { north, south, east, west } = geometry.bounds\n    this.validateBounds({ north, south, east, west })\n\n    return {\n      where: `ST_Within(\n        ${locationColumn}::geometry,\n        ST_MakeEnvelope(${west}, ${south}, ${east}, ${north}, 4326)\n      )`\n    }\n  }\n\n  /**\n   * WITHIN + POLYGON: pontos dentro de polígono\n   */\n  private generateWithinPolygonSQL(locationColumn: string): { where: string } {\n    return {\n      where: `ST_Within(\n        ${locationColumn}::geometry,\n        ST_GeomFromText($polygon, 4326)\n      )`\n    }\n  }\n\n  /**\n   * WITHIN + CIRCLE: pontos dentro de círculo\n   */\n  private generateWithinCircleSQL(geometry: any, locationColumn: string): { where: string } {\n    const { lat, lng } = geometry.center\n    const radius = geometry.radius\n\n    return {\n      where: `ST_Within(\n        ${locationColumn}::geometry,\n        ST_Buffer(ST_Point(${lng}, ${lat})::geography, ${radius})::geometry\n      )`\n    }\n  }\n\n  /**\n   * INTERSECTS + BBOX: geometrias que intersectam bbox\n   */\n  private generateIntersectsBboxSQL(geometry: any, locationColumn: string): { where: string } {\n    const { north, south, east, west } = geometry.bounds\n    this.validateBounds({ north, south, east, west })\n\n    return {\n      where: `ST_Intersects(\n        ${locationColumn},\n        ST_MakeEnvelope(${west}, ${south}, ${east}, ${north}, 4326)::geography\n      )`\n    }\n  }\n\n  /**\n   * INTERSECTS + POLYGON: geometrias que intersectam polígono\n   */\n  private generateIntersectsPolygonSQL(locationColumn: string): { where: string } {\n    return {\n      where: `ST_Intersects(\n        ${locationColumn}::geometry,\n        ST_GeomFromText($polygon, 4326)\n      )`\n    }\n  }\n\n  /**\n   * INTERSECTS + CIRCLE: geometrias que intersectam círculo\n   */\n  private generateIntersectsCircleSQL(geometry: any, locationColumn: string): { where: string } {\n    const { lat, lng } = geometry.center\n    const radius = geometry.radius\n\n    return {\n      where: `ST_Intersects(\n        ${locationColumn},\n        ST_Buffer(ST_Point(${lng}, ${lat})::geography, ${radius})\n      )`\n    }\n  }\n\n  /**\n   * CONTAINS + POINT: áreas que contêm ponto\n   */\n  private generateContainsPointSQL(geometry: any, locationColumn: string): { where: string } {\n    const [lng, lat] = geometry.coordinates\n\n    return {\n      where: `ST_Contains(\n        ${locationColumn}::geometry,\n        ST_Point(${lng}, ${lat})::geometry\n      )`\n    }\n  }\n\n  /**\n   * NEAR + POINT: pontos próximos a localização\n   */\n  private generateNearPointSQL(geometry: any, locationColumn: string, distance: number): { where: string } {\n    const [lng, lat] = geometry.coordinates\n\n    return {\n      where: `ST_DWithin(\n        ${locationColumn},\n        ST_Point(${lng}, ${lat})::geography,\n        ${distance}\n      )`\n    }\n  }\n\n  /**\n   * Valida bounds geográficos\n   */\n  private validateBounds(bounds: any): void {\n    const { north, south, east, west } = bounds\n    \n    if (north <= south || east <= west) {\n      throw new Error('Invalid bounds: north > south and east > west required')\n    }\n\n    if (north < -90 || north > 90 || south < -90 || south > 90 ||\n        east < -180 || east > 180 || west < -180 || west > 180) {\n      throw new Error('Invalid bounds: coordinates out of valid range')\n    }\n  }\n\n  /**\n   * Coleta parâmetros para binding SQL\n   */\n  private collectGeoParams(geoFilter: GeospatialFilter): Record<string, any> {\n    const params: Record<string, any> = {}\n\n    // Polygon precisa de parâmetro WKT\n    if (geoFilter.geometry.type === 'polygon') {\n      params.polygon = this.coordinatesToWKT(geoFilter.geometry.coordinates)\n    }\n\n    return params\n  }\n\n  /**\n   * Converte coordenadas GeoJSON para WKT\n   */\n  private coordinatesToWKT(coordinates: number[][]): string {\n    const points = coordinates.map(([lng, lat]) => `${lng} ${lat}`).join(', ')\n    return `POLYGON((${points}))`\n  }\n\n  /**\n   * Calcula complexidade baseada na operação e geometria\n   */\n  private calculateGeoComplexity(geoFilter: GeospatialFilter): number {\n    const { operation, geometry } = geoFilter\n    let complexity = 1 // Base\n\n    // Complexidade por operação\n    switch (operation) {\n      case 'within':\n        complexity += 2 // ST_Within é mais pesado\n        break\n      case 'intersects':\n        complexity += 1.5 // ST_Intersects médio\n        break\n      case 'contains':\n        complexity += 1.8 // ST_Contains médio-pesado\n        break\n      case 'near':\n        complexity += 1.2 // ST_DWithin mais leve\n        break\n    }\n\n    // Complexidade por geometria\n    switch (geometry.type) {\n      case 'bbox':\n        complexity += 1 // ST_MakeEnvelope simples\n        break\n      case 'polygon':\n        complexity += 2 // ST_GeomFromText + parsing\n        break\n      case 'point':\n        complexity += 0.5 // ST_Point simples\n        break\n      case 'circle':\n        complexity += 1.5 // ST_Buffer médio\n        break\n    }\n\n    // Distance adiciona complexidade\n    if (geoFilter.distance) {\n      complexity += 0.3\n    }\n\n    return Math.round(complexity * 10) / 10\n  }\n\n  // ==========================================\n  // 🧪 MÉTODOS ESTÁTICOS PARA TESTES\n  // ==========================================\n\n  /**\n   * Testa se um filtro é geoespacial (método estático)\n   */\n  static isGeospatialFilter(key: string, value: any): boolean {\n    const processor = new GeospatialProcessor()\n    return processor.canProcess(key, value)\n  }\n\n  /**\n   * Valida bounds (método estático)\n   */\n  static validateBounds(bounds: any): boolean {\n    if (!bounds || typeof bounds !== 'object') return false\n    \n    const { north, south, east, west } = bounds\n    \n    return (\n      typeof north === 'number' &&\n      typeof south === 'number' &&\n      typeof east === 'number' &&\n      typeof west === 'number' &&\n      north > south &&\n      east > west &&\n      north >= -90 && north <= 90 &&\n      south >= -90 && south <= 90 &&\n      east >= -180 && east <= 180 &&\n      west >= -180 && west <= 180\n    )\n  }\n\n  /**\n   * Cria instância configurada para testes\n   */\n  static createForTesting(): GeospatialProcessor {\n    return new GeospatialProcessor()\n  }\n}","/**\n * 🔢 Basic Processor - Filter Engine\n * \n * Especializado em filtros básicos (equals, ranges, EXISTS, etc)\n * RESPONSABILIDADES:\n * - Equals (=)\n * - Ranges (>, >=, <, <=, BETWEEN)\n * - EXISTS/NOT_EXISTS (IS NULL, IS NOT NULL)\n * - LIKE patterns\n * - Valores simples\n */\n\nimport type { \n  HorizonField,\n  FilterProcessor, \n  BasicResult \n} from '../interfaces'\n\n// ==========================================\n// 🎯 BASIC PROCESSOR\n// ==========================================\n\nexport class BasicProcessor implements FilterProcessor {\n  name = 'basic'\n\n  /**\n   * Verifica se pode processar este filtro\n   */\n  canProcess(key: string, value: any, fieldInfo?: HorizonField): boolean {\n    // Parâmetros key e fieldInfo não utilizados neste processor específico  \n    void key; void fieldInfo;\n    // Valor simples (string, number, boolean)\n    if (this.isSimpleValue(value)) {\n      return true\n    }\n\n    // Valor null\n    if (value === null) {\n      return true\n    }\n\n    // Objeto com operadores básicos\n    if (value && typeof value === 'object') {\n      const basicOperators = ['gte', 'gt', 'lte', 'lt', 'between', 'like', 'ilike', 'exists', 'equals', 'fuzzy']\n      return basicOperators.some(op => op in value)\n    }\n\n    return false\n  }\n\n  /**\n   * Processa filtro básico e retorna SQL + params\n   */\n  process(key: string, value: any, fieldInfo?: HorizonField): BasicResult {\n    // Obter nome da coluna\n    const dbColumn = (typeof fieldInfo?.db === 'string' ? fieldInfo.db : this.toSnakeCase(key))\n    \n    // Processar baseado no tipo de valor (com detecção de array via SSOT)\n    const sqlResult = this.generateBasicSQL(key, dbColumn, value, fieldInfo)\n    \n    return {\n      where: sqlResult.where,\n      params: sqlResult.params,\n      metadata: {\n        processorType: 'basic',\n        complexity: sqlResult.complexity,\n        operators: sqlResult.operators,\n        isRange: sqlResult.isRange,\n        hasSpecialFeatures: sqlResult.operators.includes('EXISTS') || sqlResult.operators.includes('LIKE'),\n      }\n    }\n  }\n\n  /**\n   * Retorna fragmentos SQL suportados\n   */\n  getSupportedFragments(): string[] {\n    return [\n      'WHERE_EQUALS',\n      'WHERE_GTE', \n      'WHERE_LTE',\n      'WHERE_BETWEEN',\n      'WHERE_LIKE',\n      'WHERE_ILIKE',\n      'WHERE_IS_NULL',\n      'WHERE_IS_NOT_NULL'\n    ]\n  }\n\n  // ==========================================\n  // 🔧 MÉTODOS PRIVADOS\n  // ==========================================\n\n  /**\n   * Gera SQL para filtros básicos (com detecção de array via SSOT)\n   */\n  private generateBasicSQL(key: string, dbColumn: string, value: any, fieldInfo?: HorizonField): {\n    where: string\n    params: Record<string, any>\n    complexity: number\n    operators: string[]\n    isRange: boolean\n  } {\n    const params: Record<string, any> = {}\n    // const operators: string[] = [] - não usado aqui\n    // let complexity = 1\n    // let isRange = false - não usado aqui\n\n    // Valor null\n    if (value === null) {\n      return {\n        where: `${dbColumn} IS NULL`,\n        params: {},\n        complexity: 1,\n        operators: ['IS_NULL'],\n        isRange: false\n      }\n    }\n\n    // Valor simples (equals) - detectar se campo é array via SSOT\n    if (this.isSimpleValue(value)) {\n      params[key] = value\n      \n      // 🎯 DETECÇÃO DE ARRAY VIA SSOT\n      const isArrayField = fieldInfo?.type?.endsWith('[]') || false\n      \n      if (isArrayField) {\n        // Campo array no PostgreSQL: usar ANY() mesmo para valor único\n        return {\n          where: `$${key} = ANY(${dbColumn})`,\n          params,\n          complexity: 1.2, // Slightly more complex than simple equals\n          operators: ['ARRAY_ANY'],\n          isRange: false\n        }\n      } else {\n        // Campo simples: usar equals normal\n        return {\n          where: `${dbColumn} = $${key}`,\n          params,\n          complexity: 1,\n          operators: ['EQUALS'],\n          isRange: false\n        }\n      }\n    }\n\n    // Objeto com operadores\n    if (value && typeof value === 'object') {\n      return this.processObjectFilter(key, dbColumn, value)\n    }\n\n    // Fallback: equals (com detecção de array)\n    params[key] = value\n    \n    // 🎯 DETECÇÃO DE ARRAY VIA SSOT (fallback)\n    const isArrayField = fieldInfo?.type?.endsWith('[]') || false\n    \n    if (isArrayField) {\n      return {\n        where: `$${key} = ANY(${dbColumn})`,\n        params,\n        complexity: 1.2,\n        operators: ['ARRAY_ANY'],\n        isRange: false\n      }\n    } else {\n      return {\n        where: `${dbColumn} = $${key}`,\n        params,\n        complexity: 1,\n        operators: ['EQUALS'],\n        isRange: false\n      }\n    }\n  }\n\n  /**\n   * Processa filtro tipo objeto\n   */\n  private processObjectFilter(key: string, dbColumn: string, value: any): {\n    where: string\n    params: Record<string, any>\n    complexity: number\n    operators: string[]\n    isRange: boolean\n  } {\n    const params: Record<string, any> = {}\n    const whereParts: string[] = []\n    const operators: string[] = []\n    let complexity = 0\n    let isRange = false\n\n    // EXISTS/NOT_EXISTS\n    if (value.exists !== undefined) {\n      if (value.exists === true) {\n        whereParts.push(`${dbColumn} IS NOT NULL`)\n        operators.push('IS_NOT_NULL')\n      } else {\n        whereParts.push(`${dbColumn} IS NULL`)\n        operators.push('IS_NULL')\n      }\n      complexity += 1\n    }\n\n    // EQUALS explícito\n    if (value.equals !== undefined) {\n      params[`${key}_equals`] = value.equals\n      whereParts.push(`${dbColumn} = $${key}_equals`)\n      operators.push('EQUALS')\n      complexity += 1\n    }\n\n    // BETWEEN\n    if (value.between && Array.isArray(value.between) && value.between.length === 2) {\n      params[`${key}_min`] = value.between[0]\n      params[`${key}_max`] = value.between[1]\n      whereParts.push(`${dbColumn} BETWEEN $${key}_min AND $${key}_max`)\n      operators.push('BETWEEN')\n      complexity += 1.5\n      isRange = true\n    }\n\n    // Range operators\n    if (value.gte !== undefined) {\n      params[`${key}_gte`] = value.gte\n      whereParts.push(`${dbColumn} >= $${key}_gte`)\n      operators.push('GTE')\n      complexity += 1\n      isRange = true\n    }\n\n    if (value.gt !== undefined) {\n      params[`${key}_gt`] = value.gt\n      whereParts.push(`${dbColumn} > $${key}_gt`)\n      operators.push('GT')\n      complexity += 1\n      isRange = true\n    }\n\n    if (value.lte !== undefined) {\n      params[`${key}_lte`] = value.lte\n      whereParts.push(`${dbColumn} <= $${key}_lte`)\n      operators.push('LTE')\n      complexity += 1\n      isRange = true\n    }\n\n    if (value.lt !== undefined) {\n      params[`${key}_lt`] = value.lt\n      whereParts.push(`${dbColumn} < $${key}_lt`)\n      operators.push('LT')\n      complexity += 1\n      isRange = true\n    }\n\n    // LIKE (case sensitive)\n    if (value.like !== undefined) {\n      params[`${key}_like`] = value.like\n      whereParts.push(`${dbColumn} LIKE $${key}_like`)\n      operators.push('LIKE')\n      complexity += 1.5\n    }\n\n    // ILIKE (case insensitive)\n    if (value.ilike !== undefined) {\n      params[`${key}_ilike`] = value.ilike\n      whereParts.push(`${dbColumn} ILIKE $${key}_ilike`)\n      operators.push('ILIKE')\n      complexity += 1.5\n    }\n\n    // FUZZY (similarity search em campos individuais)\n    if (value.fuzzy !== undefined) {\n      // Pode ser string simples ou objeto com configurações\n      let fuzzyValue: string\n      let fuzzyType: 'similarity' | 'word_similarity' = 'similarity'  // Default: frase completa\n      let fuzzyThreshold: number = 0.15  // Default threshold\n      \n      if (typeof value.fuzzy === 'string') {\n        // Fuzzy simples: { title: { fuzzy: \"apartamneto\" } }\n        fuzzyValue = value.fuzzy\n      } else if (typeof value.fuzzy === 'object' && value.fuzzy.value) {\n        // Fuzzy configurado: { title: { fuzzy: { value: \"apartamneto\", type: \"word\", threshold: 0.2 } } }\n        fuzzyValue = value.fuzzy.value\n        fuzzyType = value.fuzzy.type === 'word' ? 'word_similarity' : 'similarity'\n        fuzzyThreshold = value.fuzzy.threshold || 0.15\n      } else {\n        throw new Error(`Formato inválido para fuzzy: ${JSON.stringify(value.fuzzy)}`)\n      }\n      \n      params[`${key}_fuzzy`] = fuzzyValue\n      \n      if (fuzzyType === 'word_similarity') {\n        // word_similarity: busca palavra por palavra\n        whereParts.push(`word_similarity($${key}_fuzzy, ${dbColumn}) > ${fuzzyThreshold}`)\n        operators.push('FUZZY_WORD')\n        complexity += 3  // word_similarity é mais pesado\n      } else {\n        // similarity: compara string completa\n        whereParts.push(`similarity(${dbColumn}, $${key}_fuzzy) > ${fuzzyThreshold}`)\n        operators.push('FUZZY')\n        complexity += 2.5  // similarity também é pesado mas menos que word\n      }\n    }\n\n    // Combinar WHERE parts\n    const where = whereParts.length > 0 ? whereParts.join(' AND ') : `${dbColumn} = $${key}`\n    \n    // Se não teve nenhum operador, tratar como equals\n    if (whereParts.length === 0) {\n      params[key] = value\n      operators.push('EQUALS')\n      complexity = 1\n    }\n\n    return {\n      where,\n      params,\n      complexity: Math.round(complexity * 10) / 10,\n      operators,\n      isRange\n    }\n  }\n\n  /**\n   * Verifica se é um valor simples\n   */\n  private isSimpleValue(value: any): boolean {\n    return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'\n  }\n\n  /**\n   * Converte camelCase para snake_case\n   */\n  private toSnakeCase(str: string): string {\n    return str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`)\n  }\n\n  // ==========================================\n  // 🧪 MÉTODOS ESTÁTICOS PARA TESTES\n  // ==========================================\n\n  /**\n   * Testa se um filtro é básico (método estático)\n   */\n  static isBasicFilter(value: any): boolean {\n    const processor = new BasicProcessor()\n    return processor.canProcess('', value, undefined)\n  }\n\n  /**\n   * Testa se é valor simples (método estático)\n   */\n  static isSimpleValue(value: any): boolean {\n    const processor = new BasicProcessor()\n    return processor.isSimpleValue(value)\n  }\n\n  /**\n   * Cria instância configurada para testes\n   */\n  static createForTesting(): BasicProcessor {\n    return new BasicProcessor()\n  }\n}","/**\n * 📋 Array Processor - Filter Engine\n * \n * Especializado em operadores de array (PostgreSQL e simples)\n * RESPONSABILIDADES:\n * - OR lógico (IN para campos simples, && para arrays PostgreSQL)\n * - AND lógico (@> contains para arrays PostgreSQL)\n * - Contains e Overlaps para arrays PostgreSQL\n * - SSOT awareness para detectar tipo de campo\n */\n\nimport type { \n  HorizonField,\n  FilterProcessor, \n  ArrayFilter, \n  ArrayResult \n} from '../interfaces'\n\n// ==========================================\n// 🎯 ARRAY PROCESSOR\n// ==========================================\n\nexport class ArrayProcessor implements FilterProcessor {\n  name = 'array'\n\n  /**\n   * Verifica se pode processar este filtro\n   */\n  canProcess(key: string, value: any, fieldInfo?: HorizonField): boolean {\n    // Parâmetros key e fieldInfo não utilizados neste processor específico\n    void key; void fieldInfo;\n    if (!value || typeof value !== 'object') {\n      return false\n    }\n\n    // Detecta operadores de array\n    const arrayOperators = ['or', 'and', 'contains', 'overlaps']\n    return arrayOperators.some(op => op in value && Array.isArray(value[op]))\n  }\n\n  /**\n   * Processa filtro de array e retorna SQL + params\n   */\n  process(key: string, value: ArrayFilter, fieldInfo?: HorizonField): ArrayResult {\n    // Obter nome da coluna\n    const dbColumn = (typeof fieldInfo?.db === 'string' ? fieldInfo.db : this.toSnakeCase(key))\n    \n    // Determinar tipo de campo (array PostgreSQL ou simples)\n    const fieldType = fieldInfo?.type || 'string'\n    const isArrayField = this.isArrayField(fieldType)\n    \n    // Processar operadores de array\n    const sqlResult = this.generateArraySQL(key, dbColumn, value, isArrayField, fieldInfo)\n    \n    return {\n      where: sqlResult.where,\n      params: sqlResult.params,\n      metadata: {\n        processorType: 'array',\n        complexity: sqlResult.complexity,\n        arrayOperator: sqlResult.operator,\n        arrayType: isArrayField ? 'postgresql' : 'simple',\n        hasSpecialFeatures: isArrayField\n      }\n    }\n  }\n\n  /**\n   * Retorna fragmentos SQL suportados\n   */\n  getSupportedFragments(): string[] {\n    return [\n      'WHERE_IN',\n      'WHERE_ARRAY_CONTAINS',\n      'WHERE_ARRAY_OVERLAPS',\n      'WHERE_ARRAY_AND',\n      'WHERE_ARRAY_OR'\n    ]\n  }\n\n  // ==========================================\n  // 🔧 MÉTODOS PRIVADOS\n  // ==========================================\n\n  /**\n   * Gera SQL para operadores de array\n   */\n  private generateArraySQL(key: string, dbColumn: string, value: ArrayFilter, isArrayField: boolean, fieldInfo?: HorizonField): {\n    where: string\n    params: Record<string, any>\n    complexity: number\n    operator: 'IN' | 'contains' | 'overlaps'\n  } {\n    const params: Record<string, any> = {}\n    let where = ''\n    let complexity = 1\n    let operator: 'IN' | 'contains' | 'overlaps' = 'IN'\n\n    // OR lógico (mais comum)\n    if (value.or && Array.isArray(value.or)) {\n      this.validateArrayOperator('or', value.or, isArrayField)\n      const result = this.processOrOperator(key, dbColumn, isArrayField)\n      where = result.where\n      params[`${key}_or`] = value.or\n      operator = result.operator\n      complexity = 1.5\n    }\n    \n    // AND lógico (apenas para arrays PostgreSQL)\n    else if (value.and && Array.isArray(value.and)) {\n      if (!isArrayField) {\n        throw new Error(`AND logic cannot be applied to non-array field '${key}' (type: ${fieldInfo?.type || 'unknown'})`)\n      }\n      this.validateArrayOperator('and', value.and, isArrayField)\n      where = `${dbColumn} @> $${key}_and`\n      params[`${key}_and`] = value.and\n      operator = 'contains'\n      complexity = 2\n    }\n    \n    // Contains explícito\n    else if (value.contains && Array.isArray(value.contains)) {\n      if (!isArrayField) {\n        throw new Error(`Contains cannot be applied to non-array field '${key}' (type: ${fieldInfo?.type || 'unknown'})`)\n      }\n      this.validateArrayOperator('contains', value.contains, isArrayField)\n      where = `${dbColumn} @> $${key}_contains`\n      params[`${key}_contains`] = value.contains\n      operator = 'contains'\n      complexity = 2\n    }\n    \n    // Overlaps\n    else if (value.overlaps && Array.isArray(value.overlaps)) {\n      if (!isArrayField) {\n        throw new Error(`Overlaps cannot be applied to non-array field '${key}' (type: ${fieldInfo?.type || 'unknown'})`)\n      }\n      this.validateArrayOperator('overlaps', value.overlaps, isArrayField)\n      where = `${dbColumn} && $${key}_overlaps`\n      params[`${key}_overlaps`] = value.overlaps\n      operator = 'overlaps'\n      complexity = 1.5\n    }\n    \n    else {\n      throw new Error(`No valid array operator found in filter for key: ${key}`)\n    }\n\n    return {\n      where,\n      params,\n      complexity,\n      operator\n    }\n  }\n\n  /**\n   * Processa operador OR (IN ou overlap)\n   */\n  private processOrOperator(key: string, dbColumn: string, isArrayField: boolean): {\n    where: string\n    operator: 'IN' | 'overlaps'\n  } {\n    if (isArrayField) {\n      // Campo array PostgreSQL: usar && (overlap) com formato correto\n      return {\n        where: `${dbColumn} && ARRAY[$${key}_or]`,\n        operator: 'overlaps'\n      }\n    } else {\n      // Campo simples: usar IN com formato correto\n      return {\n        where: `${dbColumn} IN ($${key}_or)`,\n        operator: 'IN'\n      }\n    }\n  }\n\n  /**\n   * Verifica se o campo é array baseado no schema SSOT\n   */\n  private isArrayField(fieldType: string): boolean {\n    return fieldType.endsWith('[]') || fieldType.includes('array') || fieldType.includes('String[]')\n  }\n\n  /**\n   * Converte camelCase para snake_case\n   */\n  private toSnakeCase(str: string): string {\n    return str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`)\n  }\n\n  // ==========================================\n  // 🔧 VALIDAÇÕES\n  // ==========================================\n\n  /**\n   * Valida operador de array\n   */\n  private validateArrayOperator(operator: string, values: any[], isArrayField: boolean): void {\n    // Validar se array não está vazio\n    if (!Array.isArray(values) || values.length === 0) {\n      throw new Error(`${operator} operator requires non-empty array`)\n    }\n\n    // Validar se operador é suportado para tipo de campo\n    const postgresOnlyOps = ['and', 'contains', 'overlaps']\n    if (postgresOnlyOps.includes(operator) && !isArrayField) {\n      throw new Error(`${operator} operator can only be used with PostgreSQL array fields`)\n    }\n\n    // Validar tamanho do array (performance)\n    if (values.length > 100) {\n      console.warn(`Large array in ${operator} operator (${values.length} items). Consider using different approach for performance.`)\n    }\n  }\n\n  // ==========================================\n  // 🧪 MÉTODOS ESTÁTICOS PARA TESTES\n  // ==========================================\n\n  /**\n   * Testa se um filtro é de array (método estático)\n   */\n  static isArrayFilter(value: any): value is ArrayFilter {\n    const processor = new ArrayProcessor()\n    return processor.canProcess('', value, undefined)\n  }\n\n  /**\n   * Testa se campo é array (método estático)\n   */\n  static isArrayField(fieldType: string): boolean {\n    const processor = new ArrayProcessor()\n    return processor.isArrayField(fieldType)\n  }\n\n  /**\n   * Valida operadores de array (método estático)\n   */\n  static validateArrayValues(values: any[]): boolean {\n    return Array.isArray(values) && values.length > 0 && values.length <= 1000\n  }\n\n  /**\n   * Cria instância configurada para testes\n   */\n  static createForTesting(): ArrayProcessor {\n    return new ArrayProcessor()\n  }\n}","/**\n * 🔍 Filter Converter - Arquitetura Modular com Processors\n * \n * Converte filtros genéricos para WHERE clauses SQL otimizadas\n * RESPONSABILIDADES:\n * - Orquestrar processors especializados\n * - Combinar resultados de múltiplos processors\n * - Manter compatibilidade com builders existentes\n * - SSOT schema awareness\n * - Performance e debugging\n */\n\nimport type { \n  FilterConversionResult,\n  FilterConversionResultWithDebug,\n  HorizonSchema, \n  HorizonField,\n  FilterProcessor,\n  ProcessorResult,\n  ProcessorStats,\n  ProcessorInfo,\n  FilterConverterConfig\n} from './interfaces'\n\nimport { \n  createSchemaFieldMap,\n  getFieldInfo,\n  analyzeFilters,\n  validateFiltersStructure,\n  getFilterDebugInfo\n} from './helpers'\n\nimport { convertToHorizonFormat } from './schema-adapter'\n\nimport { GeospatialProcessor } from './processors/geospatial-processor'\nimport { BasicProcessor } from './processors/basic-processor'\nimport { ArrayProcessor } from './processors/array-processor'\n\n// ==========================================\n// 🎯 FILTER CONVERTER - CLASSE PRINCIPAL\n// ==========================================\n\n/**\n * Filter Converter com arquitetura modular baseada em processors especializados\n */\nexport class FilterConverter {\n  private schema?: HorizonSchema\n  private schemaFieldMap: Map<string, HorizonField> = new Map()\n  private processors: FilterProcessor[] = []\n  private config: FilterConverterConfig\n\n  constructor(schema?: HorizonSchema | any, config: FilterConverterConfig = {}) {\n    this.config = {\n      logging: false,\n      caching: false,\n      strictValidation: true,\n      ...config\n    }\n\n    // Registrar processors especializados na ordem correta\n    // (específicos primeiro, basic por último como fallback)\n    this.registerProcessor(new GeospatialProcessor())\n    this.registerProcessor(new ArrayProcessor())\n    this.registerProcessor(new BasicProcessor()) // Fallback\n\n    if (schema) {\n      // 🚨 ADAPTER TEMPORÁRIO: Detectar se é schema SSOT e converter\n      const horizonSchema = this.detectAndConvertSchema(schema)\n      this.updateSchema(horizonSchema)\n    }\n  }\n\n  /**\n   * 🚨 ADAPTER TEMPORÁRIO: Detecta formato schema e converte se necessário\n   */\n  private detectAndConvertSchema(schema: any): HorizonSchema {\n    // Se já tem formato HorizonSchema (tem entity, table, pk), usar direto\n    if (schema.entity && schema.table && schema.pk && schema.fields) {\n      return schema as HorizonSchema\n    }\n    \n    // Se é schema SSOT (tem fields com format {key, type}), converter\n    if (schema.fields && Array.isArray(schema.fields)) {\n      const firstField = schema.fields[0]\n      if (firstField && firstField.key && firstField.type) {\n        this.log('info', '🔄 ADAPTER: Convertendo schema SSOT para HorizonFormat', {\n          fieldsCount: schema.fields.length\n        })\n        return convertToHorizonFormat(schema)\n      }\n    }\n    \n    // Fallback: assumir que já está no formato correto\n    return schema as HorizonSchema\n  }\n\n  /**\n   * Atualiza schema SSOT para type awareness\n   */\n  updateSchema(schema: HorizonSchema): void {\n    this.schema = schema\n    this.schemaFieldMap = createSchemaFieldMap(schema)\n    \n    this.log('info', '📊 Schema SSOT atualizado', {\n      entity: schema.entity,\n      fieldsCount: schema.fields.length\n    })\n  }\n\n  /**\n   * Registra um processor especializado\n   */\n  registerProcessor(processor: FilterProcessor): void {\n    this.processors.push(processor)\n    this.log('debug', `✅ Processor registrado: ${processor.name}`)\n  }\n\n  // ==========================================\n  // 🔄 CONVERSÃO PRINCIPAL\n  // ==========================================\n\n  /**\n   * Converte filtros genéricos para WHERE clause SQL\n   * Interface compatível com builders existentes\n   */\n  convert(\n    filters: Record<string, any>\n  ): FilterConversionResult {\n    this.log('debug', '🔄 Iniciando conversão de filtros', { filterCount: Object.keys(filters).length })\n\n    // ✅ VALIDAÇÃO: Rejeitar fulltext em filters\n    this.validateNoFulltextInFilters(filters)\n\n    // Validação opcional\n    if (this.config.strictValidation) {\n      const validation = validateFiltersStructure(filters)\n      if (!validation.valid) {\n        throw new Error(`Invalid filters structure: ${validation.errors.join(', ')}`)\n      }\n    }\n\n    const results: ProcessorResult[] = []\n    const allParams: Record<string, any> = {}\n    const whereParts: string[] = []\n    \n    // Processar cada filtro com processor apropriado\n    Object.entries(filters).forEach(([key, value]) => {\n      try {\n        const fieldInfo = getFieldInfo(key, this.schemaFieldMap)\n        const processor = this.findProcessor(key, value, fieldInfo)\n        \n        if (processor) {\n          const result = processor.process(key, value, fieldInfo)\n          results.push(result)\n          whereParts.push(result.where)\n          Object.assign(allParams, result.params)\n          \n          this.log('debug', `✅ Filtro processado: ${key} → ${processor.name}`)\n        } else {\n          this.log('warn', `⚠️ Nenhum processor encontrado para: ${key}`, value)\n          // Tentar fallback com basic processor\n          this.tryBasicFallback(key, value, results, whereParts, allParams)\n        }\n      } catch (error) {\n        this.log('error', `❌ Erro processando filtro ${key}`, error)\n        throw new Error(`Failed to process filter '${key}': ${(error as Error).message}`)\n      }\n    })\n\n    // Combinar WHERE clauses\n    const where = whereParts.length > 0 ? whereParts.join(' AND ') : '1=1'\n    \n    // Gerar metadados combinados\n    const metadata = this.generateCombinedMetadata(results, filters)\n\n    const result = { where, params: allParams, metadata }\n    \n    this.log('info', '🎯 Conversão concluída', {\n      whereClauses: whereParts.length,\n      complexity: metadata.complexity,\n      processorsUsed: metadata.processorsUsed\n    })\n\n    return result\n  }\n\n  /**\n   * Versão de debug que inclui informações detalhadas\n   */\n  convertWithDebug(\n    filters: Record<string, any>\n  ): FilterConversionResultWithDebug {\n    const startTime = performance.now()\n    const debug: FilterConversionResultWithDebug['debug'] = { \n      processorsUsed: [],\n      fieldMappings: {}\n    }\n    \n    // Processar com debug info\n    Object.entries(filters).forEach(([key, value]) => {\n      const fieldInfo = getFieldInfo(key, this.schemaFieldMap)\n      const processor = this.findProcessor(key, value, fieldInfo)\n      const debugInfo = getFilterDebugInfo(key, value, this.schemaFieldMap)\n      \n      if (processor) {\n        const result = processor.process(key, value, fieldInfo)\n        debug.processorsUsed.push({\n          key,\n          processor: processor.name,\n          complexity: result.metadata.complexity\n        })\n      }\n      \n      debug.fieldMappings![key] = {\n        dbColumn: debugInfo.dbColumn,\n        fieldType: debugInfo.fieldType\n      }\n    })\n    \n    const result = this.convert(filters)\n    debug.totalProcessingTime = performance.now() - startTime\n    \n    return { ...result, debug }\n  }\n\n  // ==========================================\n  // 🔧 MÉTODOS PRIVADOS\n  // ==========================================\n\n  /**\n   * Encontra processor apropriado para um filtro\n   */\n  private findProcessor(key: string, value: any, fieldInfo?: HorizonField): FilterProcessor | null {\n    // Testar processors na ordem (específicos primeiro)\n    for (const processor of this.processors) {\n      if (processor.canProcess(key, value, fieldInfo)) {\n        return processor\n      }\n    }\n    return null\n  }\n\n  /**\n   * Tenta fallback com basic processor se nenhum processor específico aceitar\n   */\n  private tryBasicFallback(\n    key: string, \n    value: any, \n    results: ProcessorResult[], \n    whereParts: string[], \n    allParams: Record<string, any>\n  ): void {\n    const basicProcessor = this.processors.find(p => p.name === 'basic')\n    if (basicProcessor?.canProcess(key, value)) {\n      const result = basicProcessor.process(key, value)\n      results.push(result)\n      whereParts.push(result.where)\n      Object.assign(allParams, result.params)\n      this.log('debug', `📌 Fallback usado: ${key} → basic`)\n    } else {\n      this.log('error', `❌ Nenhum processor pode processar: ${key}`, value)\n    }\n  }\n\n  /**\n   * Gera metadados combinados de todos os processors\n   */\n  private generateCombinedMetadata(\n    results: ProcessorResult[], \n    originalFilters: Record<string, any>\n  ): FilterConversionResult['metadata'] {\n    const processorsUsed = [...new Set(results.map(r => r.metadata.processorType))]\n    const totalComplexity = results.reduce((sum, r) => sum + r.metadata.complexity, 0)\n    const analysis = analyzeFilters(originalFilters)\n    \n    return {\n      // Metadados básicos (compatibilidade)\n      hasFulltext: false, // Fulltext agora é search - mantido para compatibilidade\n      hasGeo: processorsUsed.includes('geospatial'),\n      hasRanges: analysis.hasRanges,\n      complexity: Math.round(totalComplexity * 10) / 10,\n      \n      // Metadados estendidos\n      processorsUsed,\n      totalFilters: results.length,\n      hasAdvancedFeatures: results.some(r => r.metadata.hasSpecialFeatures),\n      hasArrays: processorsUsed.includes('array'),\n      hasExists: analysis.hasExists\n    }\n  }\n\n  // ==========================================\n  // 🔄 COMPATIBILIDADE COM VERSÃO ANTERIOR\n  // ==========================================\n\n  /**\n   * Valida que fulltext não está em filters (deve estar em request.fulltext)\n   */\n  private validateNoFulltextInFilters(filters: Record<string, any>): void {\n    Object.entries(filters).forEach(([key, value]) => {\n      // Detectar tentativa de usar fulltext dentro de filters\n      if (this.isFulltextField(key) || this.isLegacyFulltextFilter(value)) {\n        throw new Error(\n          `❌ FULLTEXT NÃO PODE ESTAR EM FILTERS!\\n` +\n          `Campo '${key}' é para busca fulltext especial.\\n` +\n          `✅ Use: request.fulltext = { value: \"texto\", method: \"vector\" }\\n` +\n          `❌ Não use: filters.${key} = { search: \"texto\" }`\n        )\n      }\n    })\n  }\n\n  /**\n   * Detecta se é campo fulltext especial do SSOT\n   */\n  private isFulltextField(key: string): boolean {\n    const fieldInfo = this.schemaFieldMap.get(key)\n    if (fieldInfo && typeof fieldInfo.db === 'object') {\n      return !!(fieldInfo.db as any).fulltext_type\n    }\n    return false\n  }\n\n  /**\n   * Detecta se é filtro fulltext legado\n   */\n  private isLegacyFulltextFilter(value: any): boolean {\n    return value && typeof value === 'object' && 'search' in value\n  }\n\n  // ==========================================\n  // 📊 INFORMAÇÕES E ESTATÍSTICAS\n  // ==========================================\n\n  /**\n   * Retorna processors registrados\n   */\n  getRegisteredProcessors(): ProcessorInfo[] {\n    return this.processors.map(p => ({\n      name: p.name,\n      supportedFragments: p.getSupportedFragments()\n    }))\n  }\n\n  /**\n   * Testa qual processor seria usado para um filtro\n   */\n  testProcessorSelection(key: string, value: any): string | null {\n    const fieldInfo = getFieldInfo(key, this.schemaFieldMap)\n    const processor = this.findProcessor(key, value, fieldInfo)\n    return processor?.name || null\n  }\n\n  /**\n   * Estatísticas dos processors\n   */\n  getProcessorStats(): ProcessorStats {\n    return {\n      totalProcessors: this.processors.length,\n      processorNames: this.processors.map(p => p.name),\n      hasSchema: !!this.schema,\n      fieldsInSchema: this.schemaFieldMap.size\n    }\n  }\n\n  /**\n   * Retorna schema atual\n   */\n  getSchema(): HorizonSchema | undefined {\n    return this.schema\n  }\n\n  /**\n   * Retorna configuração atual\n   */\n  getConfig(): FilterConverterConfig {\n    return { ...this.config }\n  }\n\n  // ==========================================\n  // 🔧 UTILITÁRIOS PRIVADOS\n  // ==========================================\n\n  /**\n   * Sistema de logging configurável\n   */\n  private log(level: 'debug' | 'info' | 'warn' | 'error', message: string, data?: any): void {\n    if (!this.config.logging) return\n\n    const emoji = { debug: '🔍', info: '💡', warn: '⚠️', error: '❌' }[level]\n    console.log(`${emoji} [FilterConverter] ${message}`)\n    \n    if (data && level !== 'debug') {\n      console.log(JSON.stringify(data, null, 2))\n    }\n  }\n}\n\n// ==========================================\n// 🚀 FUNÇÕES DE CONVENIÊNCIA\n// ==========================================\n\n/**\n * Cria uma instância configurada do FilterConverter\n */\nexport function createFilterConverter(\n  schema?: HorizonSchema,\n  config?: FilterConverterConfig\n): FilterConverter {\n  return new FilterConverter(schema, config)\n}\n\n/**\n * Converte filtros de forma simples (sem instância)\n */\nexport function convertFilters(\n  filters: Record<string, any>\n): FilterConversionResult {\n  const converter = new FilterConverter()\n  return converter.convert(filters)\n}\n\n/**\n * Valida se filtros estão bem formados\n */\nexport function validateFilters(filters: Record<string, any>): { valid: boolean; errors: string[] } {\n  return validateFiltersStructure(filters)\n}","/**\n * 🔧 Processors Export - Centralização dos Processors\n * \n * Exporta todos os processors especializados do Filter Engine\n * RESPONSABILIDADES:\n * - Centralizar exportação de processors\n * - Facilitar imports nos builders\n * - Manter organização modular\n */\n\n// Processors especializados\nexport { GeospatialProcessor } from './geospatial-processor'\nexport { ArrayProcessor } from './array-processor'\nexport { BasicProcessor } from './basic-processor'\n\n// Importações para uso interno nas funções\nimport { GeospatialProcessor } from './geospatial-processor'\nimport { ArrayProcessor } from './array-processor'\nimport { BasicProcessor } from './basic-processor'\n\n// Tipos e interfaces relacionadas aos processors\nexport type {\n  FilterProcessor,\n  ProcessorResult,\n  GeospatialFilter,\n  GeospatialResult,\n  BasicFilter,\n  BasicResult,\n  ArrayFilter,\n  ArrayResult\n} from '../interfaces'\n\n// Utilitários para criação de processors customizados\nexport {\n  isGeospatialFilter,\n  isArrayFilter,\n  hasRangeOperators,\n  hasExistsOperators\n} from '../helpers'\n\n// ==========================================\n// 🚀 FUNÇÕES DE CONVENIÊNCIA\n// ==========================================\n\n/**\n * Cria instância de todos os processors padrão\n */\nexport function createDefaultProcessors(): import('../interfaces').FilterProcessor[] {\n  return [\n    new GeospatialProcessor(),\n    new ArrayProcessor(),\n    new BasicProcessor()\n  ]\n}\n\n/**\n * Cria instância apenas dos processors básicos (sem geo)\n */\nexport function createBasicProcessors(): import('../interfaces').FilterProcessor[] {\n  return [\n    new ArrayProcessor(),\n    new BasicProcessor()\n  ]\n}\n\n/**\n * Cria instância de processors específicos por nome\n */\nexport function createProcessorsByName(names: string[]): import('../interfaces').FilterProcessor[] {\n  const allProcessors = createDefaultProcessors()\n  return allProcessors.filter(p => names.includes(p.name))\n}\n\n/**\n * Retorna informações sobre processors disponíveis\n */\nexport function getProcessorInfo(): Record<string, { \n  name: string; \n  description: string; \n  supportedFeatures: string[] \n}> {\n  return {\n    geospatial: {\n      name: 'GeospatialProcessor', \n      description: 'Filtros geoespaciais com PostGIS',\n      supportedFeatures: ['bbox', 'polygon', 'radius', 'point-in-polygon']\n    },\n    array: {\n      name: 'ArrayProcessor',\n      description: 'Operadores de array PostgreSQL e listas simples',\n      supportedFeatures: ['contains', 'overlaps', 'IN-operator', 'OR/AND-logic']\n    },\n    basic: {\n      name: 'BasicProcessor',\n      description: 'Operadores fundamentais e fallback universal',\n      supportedFeatures: ['equals', 'ranges', 'exists', 'like', 'ilike', 'between']\n    }\n  }\n}","/**\n * 🔍 Fulltext Converter - Busca Fulltext Especializada\n * \n * Especializado em processar busca fulltext FORA dos filters normais\n * RESPONSABILIDADES:\n * - Processar request.fulltext (não filters.search_text)\n * - Suportar métodos: fuzzy, vector, hybrid\n * - Gerar WHERE clause para fulltext especial\n * - Trabalhar com campos fulltext e fulltext_vector\n */\n\nimport type { \n  HorizonSchema,\n  HorizonField,\n  HorizonFieldDb,\n  FulltextSearch,\n  ProcessorResult \n} from './interfaces'\n\nimport { convertToHorizonFormat } from './schema-adapter'\n\n// ==========================================\n// 🎯 FULLTEXT CONVERTER\n// ==========================================\n\nexport class FulltextConverter {\n  private schema?: HorizonSchema\n\n  constructor(schema?: HorizonSchema | any) {\n    if (schema) {\n      // 🚨 ADAPTER TEMPORÁRIO: Detectar se é schema SSOT e converter\n      this.schema = this.detectAndConvertSchema(schema)\n    }\n  }\n\n  /**\n   * 🚨 ADAPTER TEMPORÁRIO: Detecta formato schema e converte se necessário\n   */\n  private detectAndConvertSchema(schema: any): HorizonSchema {\n    // Se já tem formato HorizonSchema (tem entity, table, pk), usar direto\n    if (schema.entity && schema.table && schema.pk && schema.fields) {\n      return schema as HorizonSchema\n    }\n    \n    // Se é schema SSOT (tem fields com format {key, type}), converter\n    if (schema.fields && Array.isArray(schema.fields)) {\n      const firstField = schema.fields[0]\n      if (firstField && firstField.key && firstField.type) {\n        return convertToHorizonFormat(schema)\n      }\n    }\n    \n    // Fallback: assumir que já está no formato correto\n    return schema as HorizonSchema\n  }\n\n  /**\n   * Processa busca fulltext e retorna SQL + params\n   * SIMPLIFICADO: Apenas tsvector, sem fuzzy/hybrid\n   */\n  convert(fulltext: FulltextSearch): ProcessorResult {\n    // Validar entrada\n    this.validateFulltext(fulltext)\n    \n    // Obter campo fulltext_vector do schema\n    const { vectorField } = this.getFulltextFields()\n    \n    if (!vectorField) {\n      throw new Error('Campo fulltext_vector não encontrado no schema')\n    }\n    \n    // Gerar SQL para busca tsvector\n    const where = `${vectorField.column} @@ websearch_to_tsquery('portuguese', $fulltext_value)`\n    \n    // Coletar parâmetros\n    const params = {\n      fulltext_value: fulltext.value\n    }\n\n    return {\n      where,\n      params,\n      metadata: {\n        processorType: 'basic' as const,\n        complexity: 1.0,  // tsvector é otimizado\n        hasSpecialFeatures: false\n      }\n    }\n  }\n\n  /**\n   * Atualiza schema SSOT\n   */\n  updateSchema(schema: HorizonSchema): void {\n    this.schema = schema\n  }\n\n  /**\n   * Retorna schema atual\n   */\n  getSchema(): HorizonSchema | undefined {\n    return this.schema\n  }\n\n  // ==========================================\n  // 🔧 MÉTODOS PRIVADOS\n  // ==========================================\n\n  /**\n   * Valida entrada fulltext\n   * SIMPLIFICADO: Apenas valida o valor de busca\n   */\n  private validateFulltext(fulltext: FulltextSearch): void {\n    if (!fulltext.value || typeof fulltext.value !== 'string') {\n      throw new Error('Fulltext value é obrigatório e deve ser string')\n    }\n\n    if (fulltext.value.trim().length === 0) {\n      throw new Error('Fulltext value não pode ser vazio')\n    }\n  }\n\n  /**\n   * Obtém campos fulltext do schema SSOT\n   * Procura por campos com fulltext_type: 'text' | 'vector'\n   */\n  private getFulltextFields(): {\n    textField?: { name: string; column: string }\n    vectorField?: { name: string; column: string }\n  } {\n    if (!this.schema) {\n      // Fallback para nomes padrão se não tiver schema\n      return {\n        textField: { name: 'fulltext', column: 'fulltext' },\n        vectorField: { name: 'fulltext_vector', column: 'fulltext_vector' }\n      }\n    }\n\n    const fields = this.schema.fields\n    let textField: { name: string; column: string } | undefined\n    let vectorField: { name: string; column: string } | undefined\n\n    // Buscar campos com fulltext_type no SSOT\n    fields.forEach(field => {\n      // Obter nome da coluna corretamente\n      const column = this.getColumnName(field)\n      \n      // Verificar se field.db é objeto com fulltext_type\n      if (typeof field.db === 'object' && field.db && 'fulltext_type' in field.db) {\n        const dbConfig = field.db as HorizonFieldDb\n        \n        if (dbConfig.fulltext_type === 'text') {\n          textField = { name: field.name, column }\n        } else if (dbConfig.fulltext_type === 'vector') {\n          vectorField = { name: field.name, column }\n        }\n      }\n    })\n\n    // Log de debug para verificar se encontrou os campos\n    if (!textField || !vectorField) {\n      console.warn(`[FulltextConverter] Campos fulltext incompletos no schema:`, {\n        textField: textField ? `${textField.name} → ${textField.column}` : 'NÃO ENCONTRADO',\n        vectorField: vectorField ? `${vectorField.name} → ${vectorField.column}` : 'NÃO ENCONTRADO',\n        totalFields: fields.length\n      })\n    }\n\n    return { textField, vectorField }\n  }\n\n  /**\n   * 🔧 OBTER NOME DA COLUNA CORRETAMENTE\n   * REGRA: field.db string → usar direto | field.db object → usar field.name | undefined → usar field.name\n   */\n  private getColumnName(field: HorizonField): string {\n    if (typeof field.db === 'string') {\n      return field.db  // Coluna customizada\n    }\n    \n    if (typeof field.db === 'object' && field.db && 'column' in field.db) {\n      return field.db.column  // Objeto com column definido\n    }\n    \n    // Default: usar field.name como coluna\n    return field.name\n  }\n\n\n\n\n\n\n  // ==========================================\n  // 🧪 MÉTODOS ESTÁTICOS PARA TESTES\n  // ==========================================\n\n  /**\n   * Testa se entrada é fulltext válida\n   */\n  static isValidFulltext(fulltext: any): fulltext is FulltextSearch {\n    return (\n      fulltext &&\n      typeof fulltext === 'object' &&\n      typeof fulltext.value === 'string' &&\n      ['fuzzy', 'vector', 'hybrid'].includes(fulltext.method)\n    )\n  }\n\n  /**\n   * Cria instância para testes\n   */\n  static createForTesting(schema?: HorizonSchema): FulltextConverter {\n    return new FulltextConverter(schema)\n  }\n}","/**\n * 🎯 Multi-Request SQL Builder - Orquestrador Principal\n * \n * Gestor que coordena todos os builders e decide formato de saída\n * RESPONSABILIDADES:\n * - Analisar request e decidir quais builders usar\n * - Coordenar geração de SQLs (paralelo ou unificado)\n * - Garantir reutilização de filtros compartilhados\n */\n\nimport type { \n  GenericRequest, \n  BuildResult, \n  SQLBuilder, \n  BuilderType\n} from '../shared/interfaces'\nimport type { HorizonSchema } from '../filter/interfaces'\nimport type { OrchestratorConfig } from './core-interfaces'\nimport { FilterConverter } from '../filter/filter-converter'\nimport { FulltextConverter } from '../filter/fulltext-converter'\nimport { convertToHorizonFormat } from '../filter/schema-adapter'\n\n// ==========================================\n// 🎯 CLASSE PRINCIPAL\n// ==========================================\n\n/**\n * Orquestrador principal do Multi-Request SQL Builder\n */\nexport class MultiRequestSQLBuilder {\n  private builders: Map<BuilderType, SQLBuilder> = new Map()\n  private filterConverter: FilterConverter\n  private fulltextConverter: FulltextConverter\n  private config: OrchestratorConfig\n\n  constructor(config: OrchestratorConfig = {}) {\n    this.config = {\n      logging: { enabled: false, includeSQL: false },\n      ...config\n    }\n\n    // Inicializar converters com schema se disponível\n    this.filterConverter = new FilterConverter(config.schema)\n    this.fulltextConverter = new FulltextConverter(config.schema)\n\n    this.log('info', '🚀 MultiRequestSQLBuilder inicializado', {\n      hasSchema: !!config.schema,\n      format: 'parallel'\n    })\n  }\n\n  /**\n   * 🎯 MÉTODO PRINCIPAL - Constrói SQLs baseado no request\n   * SEMPRE RETORNA FORMATO PARALLEL - Backend escolhe como executar\n   */\n  build(request: GenericRequest): BuildResult {\n    // 1. Validar request básico PRIMEIRO\n    this.validateRequest(request)\n\n    this.log('info', '🔄 Construindo SQLs em formato parallel', {\n      include: request.include,\n      hasFilters: Object.keys(request.filters || {}).length > 0,\n      hasSearch: !!request.search\n    })\n\n    // 2. SIMPLIFICADO: Apenas list por enquanto\n    const requiredBuilders = this.determineRequiredBuilders(request)\n    \n    // 3. Filtrar apenas builders suportados\n    const supportedBuilders = requiredBuilders.filter(type => type === 'list')\n    \n    if (supportedBuilders.length === 0) {\n      throw new Error('Apenas LIST builder é suportado no momento. Use include: [\"list\"]')\n    }\n\n    this.log('debug', `📋 Builders suportados: ${supportedBuilders.join(', ')}`)\n    \n    // 4. Validar que builders necessários estão registrados\n    this.validateBuildersAvailable(supportedBuilders)\n\n    // 5. Sempre retornar formato paralelo (backend escolhe como executar)\n    return this.buildParallel(request, supportedBuilders)\n  }\n\n  /**\n   * 🔧 Registra um builder específico\n   */\n  registerBuilder(type: BuilderType, builder: SQLBuilder): void {\n    this.builders.set(type, builder)\n    this.log('info', `✅ Builder registrado: ${type}`)\n  }\n\n  /**\n   * 🔄 Atualiza schema SSOT\n   */\n  updateSchema(schema: HorizonSchema | any): void {\n    // 🚨 ADAPTER TEMPORÁRIO: Detectar se é schema SSOT e converter\n    const horizonSchema = this.detectAndConvertSchema(schema)\n    \n    this.config.schema = horizonSchema\n    this.filterConverter.updateSchema(horizonSchema)\n    this.fulltextConverter.updateSchema(horizonSchema)\n    this.log('info', '📊 Schema SSOT atualizado', {\n      entity: horizonSchema.entity,\n      fieldsCount: horizonSchema.fields.length\n    })\n  }\n\n  /**\n   * 🚨 ADAPTER TEMPORÁRIO: Detecta formato schema e converte se necessário\n   */\n  private detectAndConvertSchema(schema: any): HorizonSchema {\n    // Se já tem formato HorizonSchema (tem entity, table, pk), usar direto\n    if (schema.entity && schema.table && schema.pk && schema.fields) {\n      return schema as HorizonSchema\n    }\n    \n    // Se é schema SSOT (tem fields com format {key, type}), converter\n    if (schema.fields && Array.isArray(schema.fields)) {\n      const firstField = schema.fields[0]\n      if (firstField && firstField.key && firstField.type) {\n        this.log('info', '🔄 ADAPTER: Convertendo schema SSOT para HorizonFormat', {\n          fieldsCount: schema.fields.length\n        })\n        return convertToHorizonFormat(schema)\n      }\n    }\n    \n    // Fallback: assumir que já está no formato correto\n    return schema as HorizonSchema\n  }\n\n  // ==========================================\n  // 🔄 CONSTRUÇÃO PARALELA\n  // ==========================================\n\n  /**\n   * Constrói SQLs para execução em paralelo\n   */\n  private buildParallel(request: GenericRequest, requiredBuilders: BuilderType[]): BuildResult {\n    const sqls: Record<string, string> = {}\n    const params: Record<string, any[]> = {}\n    const buildersUsed: string[] = []\n\n    // Gerar SQL para cada builder necessário\n    requiredBuilders.forEach(builderType => {\n      const builder = this.builders.get(builderType)!\n      \n      try {\n        const result = builder.build(request)\n        sqls[builderType] = result.sql\n        params[builderType] = result.params\n        buildersUsed.push(builderType)\n        \n        this.log('debug', `✅ SQL gerado para ${builderType}`, {\n          sqlLength: result.sql.length,\n          paramsCount: result.params.length,\n          includeSQL: this.config.logging?.includeSQL ? result.sql : undefined\n        })\n      } catch (error) {\n        this.log('error', `❌ Erro ao gerar SQL para ${builderType}`, { error })\n        throw new Error(`Failed to build SQL for ${builderType}: ${error}`)\n      }\n    })\n\n    const result: BuildResult = {\n      type: 'parallel',\n      sqls,\n      params,\n      metadata: {\n        buildersUsed,\n        hasSharedFilters: Object.keys(request.filters || {}).length > 0,\n        estimatedComplexity: this.estimateComplexity(requiredBuilders, request)\n      }\n    }\n\n    this.log('info', `🎯 SQLs paralelos construídos com sucesso`, {\n      count: buildersUsed.length,\n      complexity: result.metadata?.estimatedComplexity\n    })\n\n    return result\n  }\n\n  // ==========================================\n  // 💡 NOTA: UNIFIED MODE REMOVIDO\n  // ==========================================\n  // Backend pode escolher como executar os SQLs parallel:\n  // - Executar em paralelo (Promise.all)\n  // - Unificar manualmente com CTEs se necessário\n  // Isso mantém o SQL Builder simples e dá flexibilidade total ao backend\n\n  // ==========================================\n  // 🔍 ANÁLISE E VALIDAÇÃO\n  // ==========================================\n\n  /**\n   * Determina quais builders são necessários baseado no request\n   */\n  private determineRequiredBuilders(request: GenericRequest): BuilderType[] {\n    if (!request.include || request.include.length === 0) {\n      throw new Error('Request deve conter array \"include\" com os tipos desejados')\n    }\n\n    const validBuilders: BuilderType[] = ['list', 'map', 'facets', 'item']\n    const requiredBuilders: BuilderType[] = []\n\n    request.include.forEach(type => {\n      if (validBuilders.includes(type as BuilderType)) {\n        requiredBuilders.push(type as BuilderType)\n      } else {\n        throw new Error(`Tipo de builder inválido: ${type}. Válidos: ${validBuilders.join(', ')}`)\n      }\n    })\n\n    return requiredBuilders\n  }\n\n  /**\n   * Valida se todos os builders necessários estão registrados\n   */\n  private validateBuildersAvailable(requiredBuilders: BuilderType[]): void {\n    const missingBuilders = requiredBuilders.filter(type => !this.builders.has(type))\n    \n    if (missingBuilders.length > 0) {\n      throw new Error(`Builders não registrados: ${missingBuilders.join(', ')}`)\n    }\n  }\n\n  /**\n   * Valida request básico\n   */\n  private validateRequest(request: GenericRequest): void {\n    if (!request || request === null || request === undefined) {\n      throw new Error('Request é obrigatório')\n    }\n\n    if (!request.include) {\n      throw new Error('Campo \"include\" é obrigatório')\n    }\n\n    if (!Array.isArray(request.include)) {\n      throw new Error('Campo \"include\" deve ser um array')\n    }\n\n    if (request.include.length === 0) {\n      throw new Error('Array \"include\" não pode estar vazio')\n    }\n  }\n\n  /**\n   * Estima complexidade da operação\n   */\n  private estimateComplexity(builders: BuilderType[], request: GenericRequest): 'low' | 'medium' | 'high' {\n    let complexity = builders.length\n\n    // Facets aumenta complexidade\n    if (builders.includes('facets')) complexity += 2\n    \n    // Map com geo aumenta complexidade\n    if (builders.includes('map') && request.map && 'bounds' in request.map) complexity += 1\n\n    // Múltiplos filtros aumenta complexidade\n    const filterCount = Object.keys(request.filters || {}).length\n    complexity += Math.floor(filterCount / 2) // Ajustado de /3 para /2\n    \n    // Search também aumenta complexidade\n    if (request.search) complexity += 1\n\n    if (complexity <= 2) return 'low'\n    if (complexity <= 4) return 'medium'\n    return 'high'\n  }\n\n  // ==========================================\n  // 🔧 UTILITÁRIOS\n  // ==========================================\n\n  /**\n   * Sistema de logging configurável\n   */\n  private log(level: 'debug' | 'info' | 'error', message: string, data?: any): void {\n    if (!this.config.logging?.enabled) return\n\n    const emoji = { debug: '🔍', info: '💡', error: '❌' }[level]\n    console.log(`${emoji} [MultiRequestSQLBuilder] ${message}`)\n    \n    if (data) {\n      console.log(JSON.stringify(data, null, 2))\n    }\n  }\n\n  /**\n   * Retorna estatísticas do orquestrador\n   */\n  getStats(): {\n    registeredBuilders: string[]\n    hasSchema: boolean\n  } {\n    return {\n      registeredBuilders: Array.from(this.builders.keys()),\n      hasSchema: !!this.config.schema\n    }\n  }\n}","/**\n * 🔧 Helpers Compartilhados - Multi-Request SQL Builder\n * \n * APENAS FUNÇÕES REALMENTE GENÉRICAS reutilizadas por todos os builders\n * Funções específicas foram movidas para builders/builder-name/helpers.ts\n */\n\nimport type { GenericRequest } from './interfaces'\n\n// ==========================================\n// 🔄 VALIDAÇÃO DE REQUESTS (GENÉRICA)\n// ==========================================\n\n/**\n * Valida se request contém configuração específica\n */\nexport function hasConfig<T extends keyof GenericRequest>(\n  request: GenericRequest, \n  configType: T\n): request is GenericRequest & Required<Pick<GenericRequest, T>> {\n  return request[configType] !== undefined\n}\n\n// ==========================================\n// 🏗️ CONSTRUÇÃO DE SQL (GENÉRICA)\n// ==========================================\n\n/**\n * Constrói SELECT clause baseado em fields\n */\nexport function buildSelectClause(fields?: string[]): string {\n  if (!fields || fields.length === 0) {\n    return '*'\n  }\n  \n  return fields\n    .map(field => `\"${toSnakeCase(field)}\"`)\n    .join(', ')\n}\n\n/**\n * Constrói ORDER BY clause genérica\n */\nexport function buildOrderByClause(sort?: string): string {\n  if (!sort) {\n    return 'ORDER BY \"created_at\" DESC'\n  }\n  \n  // Parse do formato: \"field ASC\" ou \"field DESC\"\n  const parts = sort.trim().split(/\\s+/)\n  const field = parts[0]\n  const direction = parts[1]?.toUpperCase() === 'ASC' ? 'ASC' : 'DESC'\n  \n  return `ORDER BY \"${toSnakeCase(field)}\" ${direction}`\n}\n\n/**\n * Constrói paginação LIMIT/OFFSET genérica\n */\nexport function buildPaginationClause(page: number = 1, limit: number = 20): {\n  limit: string\n  offset: string\n  limitValue: number\n  offsetValue: number\n} {\n  const limitValue = Math.max(1, Math.min(limit, 1000))\n  const offsetValue = Math.max(0, (page - 1) * limitValue)\n  \n  return {\n    limit: `LIMIT ${limitValue}`,\n    offset: `OFFSET ${offsetValue}`,\n    limitValue,\n    offsetValue\n  }\n}\n\n// ==========================================\n// 🔤 UTILITÁRIOS DE STRING (GENÉRICOS)\n// ==========================================\n\n/**\n * Converte camelCase para snake_case\n */\nexport function toSnakeCase(str: string): string {\n  return str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`)\n}\n\n/**\n * Converte snake_case para camelCase\n */\nexport function toCamelCase(str: string): string {\n  return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase())\n}\n\n/**\n * Normaliza nome de tabela\n */\nexport function normalizeTableName(name: string): string {\n  return `\"${toSnakeCase(name)}\"`\n}\n\n/**\n * Normaliza nome de coluna\n */\nexport function normalizeColumnName(name: string): string {\n  return `\"${toSnakeCase(name)}\"`\n}\n\n// ==========================================\n// 🧮 UTILITÁRIOS MATEMÁTICOS (GENÉRICOS)\n// ==========================================\n\n/**\n * Limita valor entre min e max\n */\nexport function clamp(value: number, min: number, max: number): number {\n  return Math.min(Math.max(value, min), max)\n}\n\n// ==========================================\n// 📊 ANÁLISE DE REQUESTS (GENÉRICA)\n// ==========================================\n\n/**\n * Analisa complexidade de um request\n */\nexport function analyzeRequestComplexity(request: GenericRequest): {\n  complexity: 'low' | 'medium' | 'high'\n  reasons: string[]\n  score: number\n} {\n  let score = 0\n  const reasons: string[] = []\n  \n  // Múltiplos includes aumentam complexidade\n  if (request.include.length > 2) {\n    score += 2\n    reasons.push(`${request.include.length} tipos de resposta solicitados`)\n  }\n  \n  // Filtros complexos\n  if (request.filters) {\n    const filterCount = Object.keys(request.filters).length\n    if (filterCount > 5) {\n      score += 2\n      reasons.push(`${filterCount} filtros aplicados`)\n    }\n    \n    // Filtros geoespaciais\n    if (request.filters.location) {\n      score += 1\n      reasons.push('Filtros geoespaciais')\n    }\n  }\n  \n  // Facetas aumentam complexidade\n  if (request.facets?.fields && request.facets.fields.length > 3) {\n    score += 2\n    reasons.push(`${request.facets.fields.length} facetas solicitadas`)\n  }\n  \n  const complexity = score >= 4 ? 'high' : score >= 2 ? 'medium' : 'low'\n  \n  return { complexity, reasons, score }\n}\n\n/**\n * Extrai metadados de um request\n */\nexport function extractRequestMetadata(request: GenericRequest): {\n  builderTypes: string[]\n  hasFilters: boolean\n  hasGeospatial: boolean\n  estimatedQueries: number\n} {\n  return {\n    builderTypes: request.include,\n    hasFilters: Boolean(request.filters && Object.keys(request.filters).length > 0),\n    hasGeospatial: Boolean(request.filters?.location),\n    estimatedQueries: request.include.length\n  }\n}\n\n// ==========================================\n// 🧪 UTILITÁRIOS DE TESTE (GENÉRICOS)\n// ==========================================\n\n/**\n * Cria request genérico para testes\n */\nexport function createTestRequest(overrides: Partial<GenericRequest> = {}): GenericRequest {\n  return {\n    include: ['list'],\n    filters: {},\n    ...overrides\n  }\n}\n\n/**\n * Valida se SQL é sintaticamente válido (básico)\n */\nexport function isValidSQL(sql: string): boolean {\n  // Validação básica de SQL\n  const hasSelect = /SELECT\\s+/i.test(sql)\n  const hasFrom = /FROM\\s+/i.test(sql)\n  const hasUnmatchedQuotes = (sql.match(/'/g) || []).length % 2 !== 0\n  \n  return hasSelect && hasFrom && !hasUnmatchedQuotes\n}\n\n/**\n * Extrai parâmetros de um SQL parametrizado\n */\nexport function extractSQLParameters(sql: string): string[] {\n  const matches = sql.match(/\\$\\w+/g)\n  return matches ? [...new Set(matches)] : []\n}","/**\n * 📋 Helpers Específicos do List Builder\n * \n * Funções utilitárias específicas para listagem com paginação\n */\n\nimport type { ListConfig } from './list-interfaces'\n\n// ==========================================\n// 📋 VALIDAÇÃO DE LIST CONFIG\n// ==========================================\n\n/**\n * Valida configuração de listagem\n */\nexport function validateListConfig(config: ListConfig): void {\n  if (config.page !== undefined && config.page < 1) {\n    throw new Error('Page deve ser >= 1')\n  }\n  \n  // Se limit for -1 ou null, é modo sync (sem limite) - permitir\n  if (config.limit === -1 || config.limit === null) {\n    return\n  }\n  \n  if (config.limit !== undefined && (config.limit < 1 || config.limit > 1000)) {\n    throw new Error('Limit deve estar entre 1 e 1000')\n  }\n}\n\n/**\n * Retorna configuração padrão para List Builder\n */\nexport function getDefaultListConfig(): Required<ListConfig> {\n  return {\n    fields: ['id'],\n    page: 1,\n    limit: 20,\n    sort: 'updated_at_desc'\n  }\n}\n\n// ==========================================\n// 🔧 MERGE DE CONFIGURAÇÃO\n// ==========================================\n\n/**\n * Merge configuração ignorando valores undefined (preserva defaults)\n */\nexport function mergeConfigWithDefaults<T extends Record<string, any>>(\n  defaults: T, \n  override: Partial<T>\n): T {\n  const result = { ...defaults } as T\n  \n  Object.entries(override).forEach(([key, value]) => {\n    if (value !== undefined) {  // 🎯 SÓ SOBRESCREVER SE NÃO FOR UNDEFINED\n      (result as any)[key] = value\n    }\n  })\n  \n  return result\n}\n\n// ==========================================\n// 🏗️ CONSTRUÇÃO DE SQL ESPECÍFICAS\n// ==========================================\n\n/**\n * Constrói clause de total count para listagem\n */\nexport function buildTotalCountClause(includeTotalCount: boolean = true): string {\n  return includeTotalCount ? ', COUNT(*) OVER() as total' : ''\n}","/**\n * 🎯 Sort Parser - Bracket Modifier Syntax\n * \n * Converte entre string URLs e objetos estruturados\n * Suporte: campo:desc, campo[modifier]:desc\n */\n\n// ==========================================\n// 🎯 INTERFACES\n// ==========================================\n\n/**\n * Objeto estruturado de ordenação\n */\nexport interface SortObject {\n  /** Campo real da tabela */\n  field: string\n  \n  /** Tipo de cálculo especial (opcional) */\n  type?: 'fts_rank' | 'proximity' | 'center'\n  \n  /** Direção da ordenação */\n  direction: 'asc' | 'desc'\n}\n\n/**\n * Input aceito pelos builders\n */\nexport type SortInput = SortObject | string | undefined\n\n// ==========================================\n// 🧠 PARSING FUNCTIONS\n// ==========================================\n\n/**\n * Converte string URL para SortObject\n * \n * @param sortString - Ex: \"valor_venda:desc\", \"location[proximity]:asc\"\n * @returns SortObject estruturado\n * \n * @example\n * parseSort(\"valor_venda:desc\")           // → { field: \"valor_venda\", direction: \"desc\" }\n * parseSort(\"title[fts_rank]:desc\")       // → { field: \"title\", type: \"fts_rank\", direction: \"desc\" }\n * parseSort(\"location[proximity]:asc\")    // → { field: \"location\", type: \"proximity\", direction: \"asc\" }\n */\nexport function parseSort(sortString: string): SortObject {\n  if (!sortString || typeof sortString !== 'string') {\n    throw new Error('Sort string é obrigatório')\n  }\n\n  // 🔄 BACKWARD COMPATIBILITY: Converter formato legado\n  // \"field_asc\" → \"field:asc\", \"field_desc\" → \"field:desc\"\n  let normalizedString = sortString\n  \n  if (!sortString.includes(':')) {\n    // Detectar formato legado: field_asc, field_desc\n    if (sortString.endsWith('_asc')) {\n      const field = sortString.replace(/_asc$/, '')\n      normalizedString = `${field}:asc`\n    } else if (sortString.endsWith('_desc')) {\n      const field = sortString.replace(/_desc$/, '')\n      normalizedString = `${field}:desc`\n    } else {\n      // Campo sem direção - assumir DESC (padrão legado)\n      normalizedString = `${sortString}:desc`\n    }\n  }\n\n  const parts = normalizedString.split(':')\n  if (parts.length !== 2) {\n    throw new Error(`Sort string inválido: \"${sortString}\". Use formato \"campo:direção\" ou \"campo[modificador]:direção\"`)\n  }\n\n  const [fieldPart, direction] = parts\n  \n  // Validar direction\n  if (!['asc', 'desc'].includes(direction.toLowerCase())) {\n    throw new Error(`Direction inválida: \"${direction}\". Use \"asc\" ou \"desc\"`)\n  }\n\n  // Check for modifier: location[proximity]\n  const modifierMatch = fieldPart.match(/^(.+)\\[(.+)\\]$/)\n  \n  if (modifierMatch) {\n    const field = modifierMatch[1]\n    const type = modifierMatch[2] as SortObject['type']\n    \n    // Validar type\n    const validTypes: SortObject['type'][] = ['fts_rank', 'proximity', 'center']\n    if (!validTypes.includes(type)) {\n      throw new Error(`Tipo de sort inválido: \"${type}\". Válidos: ${validTypes.join(', ')}`)\n    }\n    \n    return {\n      field,\n      type,\n      direction: direction.toLowerCase() as 'asc' | 'desc'\n    }\n  }\n  \n  // Simple field: valor_venda\n  return {\n    field: fieldPart,\n    direction: direction.toLowerCase() as 'asc' | 'desc'\n  }\n}\n\n/**\n * Converte SortInput (string ou object) para SortObject\n * \n * @param input - String, object ou undefined\n * @returns SortObject ou undefined\n * \n * @example\n * parseSortInput(\"valor_venda:desc\")                     // → { field: \"valor_venda\", direction: \"desc\" }\n * parseSortInput({ field: \"title\", direction: \"asc\" })  // → { field: \"title\", direction: \"asc\" }\n * parseSortInput(undefined)                              // → undefined\n */\nexport function parseSortInput(input: SortInput): SortObject | undefined {\n  if (!input) {\n    return undefined\n  }\n  \n  if (typeof input === 'string') {\n    return parseSort(input)\n  }\n  \n  if (typeof input === 'object') {\n    // Validar objeto\n    if (!input.field || !input.direction) {\n      throw new Error('SortObject deve conter \"field\" e \"direction\"')\n    }\n    \n    if (!['asc', 'desc'].includes(input.direction)) {\n      throw new Error(`Direction inválida: \"${input.direction}\". Use \"asc\" ou \"desc\"`)\n    }\n    \n    return input\n  }\n  \n  throw new Error(`Tipo de sort inválido: ${typeof input}`)\n}\n\n/**\n * Converte SortObject para string URL\n * \n * @param sortObject - Objeto estruturado\n * @returns String para URL\n * \n * @example\n * serializeSort({ field: \"valor_venda\", direction: \"desc\" })                    // → \"valor_venda:desc\"\n * serializeSort({ field: \"title\", type: \"fts_rank\", direction: \"desc\" })       // → \"title[fts_rank]:desc\"\n * serializeSort({ field: \"location\", type: \"proximity\", direction: \"asc\" })    // → \"location[proximity]:asc\"\n */\nexport function serializeSort(sortObject: SortObject): string {\n  if (!sortObject || !sortObject.field || !sortObject.direction) {\n    throw new Error('SortObject inválido')\n  }\n  \n  const { field, type, direction } = sortObject\n  \n  if (type) {\n    return `${field}[${type}]:${direction}`\n  }\n  \n  return `${field}:${direction}`\n}\n\n// ==========================================\n// 🔧 HELPER FUNCTIONS\n// ==========================================\n\n/**\n * Verifica se sort é um campo especial (com modificador)\n */\nexport function isSpecialSort(sort: SortObject): boolean {\n  return !!sort.type\n}\n\n/**\n * Verifica se sort é FTS ranking\n */\nexport function isFtsRankSort(sort: SortObject): boolean {\n  return sort.type === 'fts_rank'\n}\n\n/**\n * Verifica se sort é geográfico\n */\nexport function isGeoSort(sort: SortObject): boolean {\n  return sort.type === 'proximity' || sort.type === 'center'\n}\n\n/**\n * Retorna sort padrão\n */\nexport function getDefaultSort(): SortObject {\n  return { field: 'created_at', direction: 'desc' }\n}\n\n// ==========================================\n// 🧪 VALIDATION HELPERS\n// ==========================================\n\n/**\n * Valida se string de sort está no formato correto\n */\nexport function isValidSortString(sortString: string): boolean {\n  try {\n    parseSort(sortString)\n    return true\n  } catch {\n    return false\n  }\n}\n\n/**\n * Valida se SortObject está correto\n */\nexport function isValidSortObject(sortObject: any): sortObject is SortObject {\n  return (\n    typeof sortObject === 'object' &&\n    sortObject !== null &&\n    typeof sortObject.field === 'string' &&\n    typeof sortObject.direction === 'string' &&\n    ['asc', 'desc'].includes(sortObject.direction) &&\n    (sortObject.type === undefined || ['fts_rank', 'proximity', 'center'].includes(sortObject.type))\n  )\n}","/**\n * 🔧 SQL Params Converter - Helper Genérico\n * \n * Converte parâmetros nomeados ($param) para ordenados ($1, $2) para PrismaRaw\n */\n\n/**\n * Converte parâmetros nomeados para ordenados (para PrismaRaw)\n */\nexport function convertNamedParamsToOrdered(sql: string, namedParams: Record<string, any>): {\n  cleanSQL: string\n  orderedParams: any[]\n} {\n  const orderedParams: any[] = []\n  let paramIndex = 1\n  \n  // Mapear cada parâmetro nomeado para um índice ordenado\n  const cleanSQL = sql.replace(/\\$([a-zA-Z_][a-zA-Z0-9_]*)/g, (match, paramName) => {\n    if (paramName in namedParams) {\n      orderedParams.push(namedParams[paramName])\n      return `$${paramIndex++}`\n    }\n    return match\n  })\n  \n  return {\n    cleanSQL,\n    orderedParams\n  }\n}","/**\n * 📋 List Builder - Postgre-Search-SQL-Builder\n * \n * Gerador de SQL para listagem com paginação e total\n * RESPONSABILIDADES:\n * - Converter request genérico → SQL de listagem\n * - Incluir COUNT(*) OVER() para total\n * - Aplicar paginação (LIMIT/OFFSET)\n * - Aplicar ordenação\n */\n\nimport type { GenericRequest, SQLBuilder, SQLBuildResult, SortInput } from '../../shared/interfaces'\nimport type { FulltextSearch } from '../../filter/interfaces'\nimport { FilterConverter } from '../../filter/filter-converter'\nimport { FulltextConverter } from '../../filter/fulltext-converter'\nimport { hasConfig } from '../../shared/helpers'\nimport { validateListConfig, getDefaultListConfig, buildTotalCountClause, mergeConfigWithDefaults } from './list-helpers'\nimport { parseSortInput } from '../../shared/sort-parser'\nimport { convertNamedParamsToOrdered } from '../../shared/sql-params-converter'\n\n// ==========================================\n// 🌍 TIPOS GEOGRÁFICOS\n// ==========================================\n\ninterface GeographicPoint {\n  lat: number\n  lng: number\n}\n\ninterface GeographicCircle {\n  type: 'circle'\n  center: GeographicPoint\n  radius: number\n}\n\ninterface GeographicBounds {\n  north: number\n  south: number\n  east: number\n  west: number\n}\n\ninterface GeographicBBox {\n  type: 'bbox'\n  bounds: GeographicBounds\n}\n\ninterface LocationFilter {\n  operation: 'within'\n  geometry: GeographicCircle | GeographicBBox\n}\n\ninterface LegacyPointFilter {\n  point: GeographicPoint & { radius?: number }\n  bounds?: GeographicBounds\n}\n\n// ==========================================\n// 🏗️ CONFIGURAÇÃO DO BUILDER\n// ==========================================\n\nexport interface ListBuilderConfig {\n  /** Nome da tabela principal */\n  tableName?: string\n  \n  /** Nome da coluna de localização (para geo) */\n  locationColumn?: string\n  \n  /** Incluir total por padrão */\n  includeTotalByDefault?: boolean\n  \n  /** Limite máximo de registros */\n  maxLimit?: number\n}\n\n// ==========================================\n// 🎯 CLASSE PRINCIPAL\n// ==========================================\n\n/**\n * Builder especializado em gerar SQLs de listagem\n */\nexport class ListBuilder implements SQLBuilder {\n  private filterConverter: FilterConverter\n  private fulltextConverter: FulltextConverter\n  private config: Required<ListBuilderConfig>\n\n  constructor(\n    filterConverter: FilterConverter,\n    fulltextConverterOrConfig?: FulltextConverter | ListBuilderConfig,\n    config?: ListBuilderConfig\n  ) {\n    this.filterConverter = filterConverter\n    \n    // Detectar se 2º parâmetro é FulltextConverter ou config\n    if (fulltextConverterOrConfig && typeof fulltextConverterOrConfig === 'object') {\n      // Se tem método 'convert', é FulltextConverter\n      if ('convert' in fulltextConverterOrConfig && typeof fulltextConverterOrConfig.convert === 'function') {\n        this.fulltextConverter = fulltextConverterOrConfig as FulltextConverter\n        // config é o 3º parâmetro\n      } else {\n        // É config direto (compatibilidade com testes antigos)\n        this.fulltextConverter = new FulltextConverter()\n        config = fulltextConverterOrConfig as ListBuilderConfig\n      }\n    } else {\n      this.fulltextConverter = new FulltextConverter()\n    }\n    \n    // Aplicar config corretamente\n    const defaultConfig = {\n      tableName: 'property',\n      locationColumn: 'location',\n      includeTotalByDefault: true,\n      maxLimit: 1000\n    }\n    \n    this.config = { ...defaultConfig, ...config } as Required<ListBuilderConfig>\n  }\n\n  /**\n   * Verifica se este builder suporta o tipo solicitado\n   */\n  supports(type: string): boolean {\n    return type === 'list'\n  }\n\n  /**\n   * Constrói SQL de listagem baseado no request\n   */\n  build(request: GenericRequest): SQLBuildResult {\n    // Verificar se tem configuração de lista\n    if (!hasConfig(request, 'list')) {\n      throw new Error('Request deve conter configuração \"list\"')\n    }\n\n    // Merge config usando função que ignora undefined (preserva defaults)\n    const defaultConfig = getDefaultListConfig()\n    const listConfig = mergeConfigWithDefaults(defaultConfig, request.list || {})\n    \n    // Casos especiais: fields undefined = SELECT *\n    if (request.list?.fields === undefined) {\n      (listConfig as any).fields = undefined\n    }\n    \n    // Casos especiais: limit explicitamente undefined = sem limite (modo sync)\n    if (request.list && 'limit' in request.list && request.list.limit === undefined) {\n      (listConfig as any).limit = undefined\n    }\n    \n    // Validar limites primeiro (mais específicos)\n    this.validateLimits(listConfig)\n    \n    // Validar configuração geral\n    validateListConfig(listConfig)\n\n    // 1. Processar filtros normais\n    const filterResult = this.filterConverter.convert(request.filters || {})\n    let whereClause = filterResult.where\n    let allParams = { ...filterResult.params }\n\n    // 2. Processar search se presente\n    let searchWhereClause = ''\n    if (request.search) {\n      const searchResult = this.fulltextConverter.convert(request.search)\n      searchWhereClause = searchResult.where\n      allParams = { ...allParams, ...searchResult.params }\n    }\n\n    // 3. Combinar WHERE clauses\n    const combinedWhere = this.combineWhereClauses(whereClause, searchWhereClause)\n\n    // 4. Construir SELECT clause (com FTS_RANK e GEO_PROXIMITY se necessário)\n    const selectClause = this.buildSelectClause(listConfig, request.search, request)\n\n    // 5. Construir ORDER BY clause (usar listConfig.sort que já vem do request.list.sort)\n    const orderByClause = this.buildOrderByClause(listConfig.sort)\n\n    // 6. Construir LIMIT/OFFSET para paginação\n    const paginationClause = this.buildPaginationClause(listConfig)\n\n    // 7. Montar SQL completo\n    const sql = `\nSELECT ${selectClause}\nFROM \"${this.config.tableName}\"\nWHERE ${combinedWhere}\n${orderByClause}\n${paginationClause}\n    `.trim()\n\n    // 8. Converter parâmetros nomeados para array ordenado (para PrismaRaw)\n    const { cleanSQL, orderedParams } = convertNamedParamsToOrdered(sql, allParams)\n\n    return {\n      sql: this.cleanSQL(cleanSQL),\n      params: orderedParams,\n      metadata: {\n        complexity: filterResult.metadata.complexity,\n        hasGeo: filterResult.metadata.hasGeo,\n        hasFulltext: !!request.search\n      }\n    }\n  }\n\n  /**\n   * Retorna filtros obrigatórios para este builder\n   */\n  getRequiredFilters(): string[] {\n    return [] // List builder não tem filtros obrigatórios\n  }\n\n  // ==========================================\n  // 🔧 MÉTODOS PRIVADOS\n  // ==========================================\n\n  /**\n   * Constrói SELECT clause com campos, total, FTS_RANK e GEO_PROXIMITY se necessário\n   */\n  private buildSelectClause(listConfig: any, search?: FulltextSearch, request?: any): string {\n    // Campos básicos\n    const baseSelect = this.buildBaseSelectClause(listConfig.fields)\n    \n    // Total count\n    const totalClause = buildTotalCountClause(this.config.includeTotalByDefault)\n    \n    // FTS_RANK se necessário (usar listConfig.sort)\n    const ftsRankClause = this.buildFtsRankClause(listConfig.sort, search)\n    \n    // GEO_PROXIMITY se necessário (usar listConfig.sort)\n    const geoProximityClause = this.buildGeoProximityClause(listConfig.sort, request?.filters)\n    \n    return `${baseSelect}${totalClause}${ftsRankClause}${geoProximityClause}`\n  }\n\n  /**\n   * Constrói SELECT básico de campos\n   */\n  private buildBaseSelectClause(fields?: string[]): string {\n    if (!fields || fields.length === 0) {\n      return '*'\n    }\n    \n    return fields\n      .map(field => `\"${field}\"`)\n      .join(', ')\n  }\n\n  /**\n   * Constrói FTS_RANK clause se sort tem type='fts_rank' e há search\n   * SIMPLIFICADO: Apenas ts_rank do tsvector (sem fuzzy em textos longos)\n   */\n  private buildFtsRankClause(sort?: SortInput, search?: FulltextSearch): string {\n    const sortObj = parseSortInput(sort)\n    \n    if (!sortObj || sortObj.type !== 'fts_rank' || !search) {\n      return ''\n    }\n\n    // 🔥 RANKING APENAS DO TSVECTOR (fuzzy removido)\n    const searchParam = 'search_value'\n    \n    return `, ts_rank(fulltext_vector, websearch_to_tsquery('portuguese', $${searchParam})) as fts_rank`\n  }\n\n  /**\n   * Constrói LOCATION clause para proximity ou center\n   */\n  private buildGeoProximityClause(sort?: SortInput, filters?: any): string {\n    const sortObj = parseSortInput(sort)\n    \n    if (!sortObj || (sortObj.type !== 'proximity' && sortObj.type !== 'center')) {\n      return ''\n    }\n\n    if (sortObj.type === 'proximity') {\n      // 🌍 DISTÂNCIA DE UM PONTO ESPECÍFICO - APENAS DADOS REAIS\n      const geoCenter = this.extractGeoCenterFromFilters(filters)\n      \n      if (!geoCenter) {\n        // ❌ SEM DADOS GEOGRÁFICOS - FALHAR\n        throw new Error('Sort proximity requer dados geográficos nos filtros (location com point/radius)')\n      }\n\n      // 📍 DISTÂNCIA DO PONTO REAL DOS FILTROS\n      return `, ST_Distance(${this.config.locationColumn}, ST_Point(${geoCenter.lng}, ${geoCenter.lat})::geography) as location_proximity`\n    }\n\n    if (sortObj.type === 'center') {\n      // 🎯 CENTRALIDADE DENTRO DE UMA ÁREA - APENAS DADOS REAIS\n      const geoBounds = this.extractGeoBoundsFromFilters(filters)\n      \n      if (!geoBounds) {\n        // ❌ SEM DADOS GEOGRÁFICOS - FALHAR\n        throw new Error('Sort center requer dados geográficos nos filtros (location com bbox/polygon)')\n      }\n\n      // 📊 DISTÂNCIA DO CENTROIDE DA ÁREA REAL DOS FILTROS\n      return `, ST_Distance(${this.config.locationColumn}, ST_Centroid(${geoBounds.geometry})) as location_center`\n    }\n\n    return ''\n  }\n\n  /**\n   * Extrai coordenadas do centro geográfico dos filtros\n   */\n  private extractGeoCenterFromFilters(filters?: any): { lat: number; lng: number } | null {\n    if (!filters) return null\n\n    // Procurar por filtro de localização com radius\n    for (const [key, value] of Object.entries(filters)) {\n      if (key === 'location' && value && typeof value === 'object') {\n        // Formato: { operation: 'within', geometry: { type: 'circle', center: { lat, lng }, radius } }\n        const locationValue = value as LocationFilter | LegacyPointFilter\n        if ('geometry' in locationValue && locationValue.geometry?.type === 'circle' && locationValue.geometry.center) {\n          return {\n            lat: locationValue.geometry.center.lat,\n            lng: locationValue.geometry.center.lng\n          }\n        }\n        \n        // Formato alternativo: { point: { lat, lng, radius } }\n        if ('point' in locationValue && locationValue.point?.lat && locationValue.point.lng) {\n          return {\n            lat: locationValue.point.lat,\n            lng: locationValue.point.lng\n          }\n        }\n      }\n    }\n\n    return null\n  }\n\n  /**\n   * Extrai bounds geográficos (BBOX ou Polygon) dos filtros\n   */\n  private extractGeoBoundsFromFilters(filters?: any): { geometry: string } | null {\n    if (!filters) return null\n\n    // Procurar por filtro de localização com BBOX ou Polygon\n    for (const [key, value] of Object.entries(filters)) {\n      if (key === 'location' && value && typeof value === 'object') {\n        \n        // Formato BBOX: { operation: 'within', geometry: { type: 'bbox', bounds: { north, south, east, west } } }\n        const locationValue = value as LocationFilter | LegacyPointFilter | any\n        if ('geometry' in locationValue && locationValue.geometry?.type === 'bbox' && locationValue.geometry.bounds) {\n          const { north, south, east, west } = locationValue.geometry.bounds\n          return {\n            geometry: `ST_MakeEnvelope(${west}, ${south}, ${east}, ${north}, 4326)`\n          }\n        }\n        \n        // Formato Polygon: { operation: 'within', geometry: { type: 'polygon', coordinates: [...] } }\n        if ('geometry' in locationValue && locationValue.geometry?.type === 'polygon' && locationValue.geometry.coordinates) {\n          const coords = locationValue.geometry.coordinates[0] // Primeiro anel do polygon\n          const coordsStr = coords.map((coord: number[]) => `${coord[0]} ${coord[1]}`).join(',')\n          return {\n            geometry: `ST_GeomFromText('POLYGON((${coordsStr}))', 4326)`\n          }\n        }\n\n        // Formato legacy BBOX: { bounds: { north, south, east, west } }\n        if ('bounds' in locationValue && locationValue.bounds) {\n          const { north, south, east, west } = locationValue.bounds\n          return {\n            geometry: `ST_MakeEnvelope(${west}, ${south}, ${east}, ${north}, 4326)`\n          }\n        }\n      }\n    }\n\n    return null\n  }\n\n  /**\n   * Combina WHERE clauses de filtros + search\n   */\n  private combineWhereClauses(filterWhere: string, searchWhere: string): string {\n    // Se não há search, usa só filtros\n    if (!searchWhere) {\n      return filterWhere\n    }\n    \n    // Se filtros é \"1=1\" (vazio), usa só search\n    if (filterWhere === '1=1') {\n      return searchWhere\n    }\n    \n    // Combina ambos com AND\n    return `(${filterWhere}) AND (${searchWhere})`\n  }\n\n  /**\n   * Constrói ORDER BY clause - Suporte SortObject e backward compatibility\n   */\n  private buildOrderByClause(sort?: SortInput): string {\n    // Parse input para SortObject\n    const sortObj = parseSortInput(sort)\n    \n    if (!sortObj) {\n      return 'ORDER BY \"created_at\" DESC'\n    }\n    \n    const { field, type, direction } = sortObj\n    const directionUpper = direction.toUpperCase()\n    \n    // ==========================================\n    // 🎯 SORTS ESPECIAIS COM MODIFICADORES\n    // ==========================================\n    \n    if (type === 'fts_rank') {\n      // FTS_RANK: ts_rank(fulltext_vector, query) \n      return `ORDER BY fts_rank ${directionUpper}`\n    }\n    \n    if (type === 'proximity') {\n      // GEO PROXIMITY: ST_Distance(location, point)\n      return `ORDER BY location_proximity ${directionUpper}`\n    }\n    \n    if (type === 'center') {\n      // GEO CENTER: ST_Distance(location, ST_Centroid(bounds))\n      return `ORDER BY location_center ${directionUpper}`\n    }\n    \n    // ==========================================\n    // 📋 CAMPOS NORMAIS (sem modificador)\n    // ==========================================\n    \n    return `ORDER BY \"${field}\" ${directionUpper}`\n  }\n\n  /**\n   * Constrói LIMIT/OFFSET para paginação\n   */\n  private buildPaginationClause(listConfig: any): string {\n    // Modo sync (sem limite)\n    if (listConfig.limit === -1 || listConfig.limit === null || listConfig.limit === undefined) {\n      return ''\n    }\n    \n    const limit = Math.max(1, Math.min(listConfig.limit, this.config.maxLimit))\n    const offset = Math.max(0, (listConfig.page - 1) * limit)\n    \n    let clause = `LIMIT ${limit}`\n    if (offset > 0) {\n      clause += `\\nOFFSET ${offset}`\n    }\n    \n    return clause\n  }\n\n  /**\n   * Valida limites de paginação\n   */\n  private validateLimits(listConfig: any): void {\n    // Se limit for -1, null ou undefined, é modo sync (sem limite)\n    if (listConfig.limit === -1 || listConfig.limit === null || listConfig.limit === undefined) {\n      // Modo sync não precisa validar limite\n      return\n    }\n\n    if (listConfig.limit > this.config.maxLimit) {\n      throw new Error(`Limit não pode exceder ${this.config.maxLimit}`)\n    }\n\n    if (listConfig.page < 1) {\n      throw new Error('Page deve ser >= 1')\n    }\n\n    // Validar se não está tentando pular muitos registros (proteção contra deep pagination)\n    const skip = (listConfig.page - 1) * listConfig.limit\n    if (skip > 100000) {\n      throw new Error('Paginação muito profunda. Use cursor-based pagination para grandes offsets.')\n    }\n  }\n\n  /**\n   * Limpa e formata SQL final\n   */\n  private cleanSQL(sql: string): string {\n    return sql\n      .split('\\n')\n      .map(line => line.trim())\n      .filter(line => line.length > 0)\n      .join('\\n')\n      .replace(/\\n{2,}/g, '\\n')\n  }\n\n  // ==========================================\n  // 🧪 MÉTODOS PARA TESTE E DEBUG\n  // ==========================================\n\n  /**\n   * Retorna configuração atual (para testes)\n   */\n  getConfig(): Required<ListBuilderConfig> {\n    return { ...this.config }\n  }\n\n  /**\n   * Gera SQL de exemplo para debug\n   */\n  generateExampleSQL(): SQLBuildResult {\n    const exampleRequest: GenericRequest = {\n      filters: { \n        status: 'active',\n        category: { or: ['tech', 'business'] }\n      },\n      include: ['list'],\n      list: {\n        fields: ['id', 'title', 'status'],\n        page: 1,\n        limit: 20,\n        sort: 'updated_at_desc'\n      }\n    }\n\n    return this.build(exampleRequest)\n  }\n\n}\n\n// ==========================================\n// 🚀 FUNÇÃO DE CONVENIÊNCIA\n// ==========================================\n\n/**\n * Cria uma instância configurada do ListBuilder\n */\nexport function createListBuilder(\n  filterConverter: FilterConverter,\n  fulltextConverter?: FulltextConverter,\n  config?: ListBuilderConfig\n): ListBuilder {\n  return new ListBuilder(filterConverter, fulltextConverter, config)\n}","/**\n * 🎯 Postgre-Search-SQL-Builder - Ponto de Entrada Principal\n * \n * Exports principais do Filter Engine e builders funcionais\n */\n\n// Filter Engine\nexport { FilterConverter, createFilterConverter, convertFilters, validateFilters } from './filter/filter-converter'\nexport type { \n  HorizonSchema, \n  HorizonField, \n  GeospatialFilter, \n  FilterConversionResult,\n  FilterConversionResultWithDebug,\n  FilterProcessor,\n  ProcessorResult,\n  ProcessorStats,\n  ProcessorInfo,\n  ConversionOptions,\n  FilterConverterConfig,\n  FulltextSearch,\n  BasicFilter,\n  ArrayFilter\n} from './filter/interfaces'\n\n// Filter Processors\nexport {\n  GeospatialProcessor,\n  ArrayProcessor,\n  BasicProcessor,\n  createDefaultProcessors,\n  createBasicProcessors,\n  createProcessorsByName,\n  getProcessorInfo\n} from './filter/processors'\n\n// Filter Helpers\nexport {\n  toSnakeCase,\n  toCamelCase,\n  getDbColumnName,\n  isSimpleValue,\n  isArrayField,\n  isFulltextFilter,\n  isGeospatialFilter,\n  isArrayFilter,\n  hasRangeOperators,\n  hasExistsOperators,\n  analyzeFilters,\n  validateGeoBounds,\n  validateGeoFilter,\n  normalizeSearchText\n} from './filter/helpers'\n\n// // Helpers (comentado temporariamente)\n// export {\n//   hasConfig,\n//   validateListConfig,\n//   validateMapConfig,\n//   validateFacetsConfig,\n//   buildSelectClause,\n//   buildOrderByClause,\n//   buildPaginationClause,\n//   buildTotalCountClause,\n//   buildBboxWhereClause,\n//   buildPolygonWhereClause,\n//   buildRadiusWhereClause,\n//   normalizeTableName,\n//   normalizeColumnName,\n//   getDefaultListConfig,\n//   getDefaultMapConfig,\n//   getDefaultFacetsConfig,\n//   getDefaultItemConfig,\n//   clamp,\n//   calculateHistogramBars,\n//   analyzeRequestComplexity,\n//   extractRequestMetadata,\n//   createTestRequest,\n//   isValidSQL,\n//   extractSQLParameters\n// } from './shared/helpers'\n\n// // SQL Fragments (comentado temporariamente)\n// export {\n//   WHERE_EQUALS,\n//   WHERE_IN,\n//   WHERE_BETWEEN,\n//   WHERE_GTE,\n//   WHERE_LTE,\n//   WHERE_LIKE,\n//   WHERE_FULLTEXT,\n//   WHERE_ARRAY_CONTAINS,\n//   WHERE_ARRAY_OVERLAPS,\n//   WHERE_BBOX,\n//   WHERE_POLYGON,\n//   WHERE_RADIUS,\n//   SELECT_COORDINATES,\n//   SELECT_FIELDS,\n//   SELECT_WITH_TOTAL,\n//   SELECT_COUNT,\n//   SELECT_AGGREGATIONS,\n//   ORDER_BY_FIELD,\n//   ORDER_BY_DEFAULT,\n//   ORDER_BY_MULTIPLE,\n//   ORDER_BY_RELEVANCE,\n//   INNER_JOIN,\n//   LEFT_JOIN,\n//   MANY_TO_MANY_JOIN,\n//   CTE_BASE_FILTERED,\n//   CTE_PAGINATED,\n//   CTE_AGGREGATED,\n//   CTE_FACET_TERMS,\n//   CTE_FACET_HISTOGRAM,\n//   CTE_FACET_DATE_HISTOGRAM,\n//   applyFragment,\n//   combineWhereFragments,\n//   combineWhereFragmentsOr,\n//   buildCompleteCTE,\n//   buildUnionSelect\n// } from './shared/sql-fragments'\n\n// ==========================================\n// 🚀 API PRINCIPAL\n// ==========================================\n\n// Exportar o Orchestrator como API principal\nexport { MultiRequestSQLBuilder as PostgreSearchSQLBuilder } from './core/orchestrator'\n\n// Exportar o ListBuilder individual\nexport { ListBuilder } from './builders/list/list-builder'\nexport { FulltextConverter } from './filter/fulltext-converter'\n\n// Imports para createSQLBuilder\nimport { MultiRequestSQLBuilder } from './core/orchestrator'\nimport { ListBuilder } from './builders/list/list-builder'\nimport { FilterConverter } from './filter/filter-converter'\nimport { FulltextConverter } from './filter/fulltext-converter'\nimport { BasicProcessor } from './filter/processors/basic-processor'\n\n// Tipos do core\nexport type { \n  GenericRequest,\n  BuildResult,\n  SQLBuilder,\n  BuilderType,\n  OutputFormat \n} from './shared/interfaces'\n\n// ==========================================\n// 🚀 FUNÇÕES DE CONVENIÊNCIA\n// ==========================================\n\n/**\n * Cria uma instância configurada do PostgreSearchSQLBuilder\n */\nexport function createSQLBuilder(config?: {\n  schema?: import('./filter/interfaces').HorizonSchema\n  logging?: boolean\n}) {\n  // Configurar converters\n  const filterConverter = new FilterConverter(config?.schema)\n  const fulltextConverter = new FulltextConverter(config?.schema)\n  const basicProcessor = new BasicProcessor()\n  \n  filterConverter.registerProcessor(basicProcessor)\n  \n  // Configurar orchestrator\n  const orchestrator = new MultiRequestSQLBuilder({\n    schema: config?.schema,\n    logging: { enabled: config?.logging || false, includeSQL: false }\n  })\n  \n  // Registrar apenas ListBuilder por enquanto\n  const listBuilder = new ListBuilder(filterConverter, fulltextConverter)\n  orchestrator.registerBuilder('list', listBuilder)\n  \n  return orchestrator\n}\n\n/**\n * Versão do pacote\n */\nexport const VERSION = '1.0.0'"]}