# 🏗️ Plano de Implementação Multi-Search v2.0

## 📋 **CHECKLIST COMPLETO - NADA FICA DE FORA**

### **🔧 ETAPA 1: Interfaces Base** ✅ COMPLETO
- [x] Criar interfaces MultiSearchRequest/Response limpas
- [x] Interface GeospatialFilter com bbox/polygon  
- [x] Interface PrismaMultiQuery para transaction
- [x] Validação Zod completa
- [x] Fragmentação em arquivo separado: `multi-search-interfaces.ts`

### **🔧 ETAPA 2: Mapper Geoespacial** ✅ COMPLETO
- [x] Função extractGeospatialQuery (bbox/polygon → SQL)
- [x] Função prismaWhereToSQL (conversão básica)
- [x] Fragmentação em arquivo separado: `geospatial-utils.ts`
- [x] Teste isolado passando: `geospatial-function.test.ts`

### **🔧 ETAPA 3: Multi Request Mapper** ✅ COMPLETO
- [x] Classe MultiSearchMapper completa
- [x] Método mapMultiSearch (request → queries)
- [x] Método buildListQueries (paginação)
- [x] Método buildMapQueries (sem paginação + geo)
- [x] Validação completa de entrada
- [x] Fragmentação em arquivo separado: `multi-search-mapper.ts`
- [x] Teste isolado passando: `multi-search-mapper.test.ts`

### **🔧 ETAPA 4: Service com Transaction** ✅ COMPLETO
- [x] Classe PrismaMultiService completa
- [x] Método multiSearch com $transaction
- [x] Processamento paralelo de queries
- [x] Separação automática property/relations
- [x] Cálculo de bounds geográficos
- [x] Logs de entrada/saída
- [x] Fragmentação em arquivo separado: `multi-search-service.ts`
- [x] Teste isolado passando: `multi-search-service.test.ts`

### **🔧 ETAPA 5: Integração Completa** ✅ COMPLETO
- [x] Teste mapper + service juntos
- [x] Cenário bbox (lista + mapa + meta)
- [x] Cenário polygon (só mapa)
- [x] Validação de erros
- [x] Performance com transaction
- [x] Teste end-to-end passando: `integration-complete.test.ts`

### **🔧 ETAPA 6: Documentação** ✅ COMPLETO
- [x] Documentar implementação realizada
- [x] Exemplos de uso completos
- [x] Breaking changes documentation

### **🔧 ETAPA 7: Schema Awareness** ✅ COMPLETO
- [x] Integrar HorizonSchema no MultiSearchMapper
- [x] Expandir schema de teste com geo-point location
- [x] Implementar validação de campos vs schema
- [x] Adicionar type safety para filtros geoespaciais
- [x] Criar testes com schema awareness
- [x] Documentar nova funcionalidade

## 🎯 **IMPLEMENTAÇÃO COMPLETA - FUNCIONANDO 100%**

✅ **TODOS OS TESTES PASSANDO**
✅ **ARQUITETURA FRAGMENTADA CORRETAMENTE**
✅ **INTEGRAÇÃO END-TO-END FUNCIONAL**

## 📁 **ESTRUTURA DE ARQUIVOS CRIADA**

```
src/search-request-to-prisma-mapper/
├── index.ts                          (arquivo original + exports)
├── multi-search-interfaces.ts        (interfaces fragmentadas)
├── multi-search-mapper.ts            (mapper novo)
├── geospatial-utils.ts               (funções geo)
├── docs/
│   └── readme.md                     (doc movida)
└── tests/
    ├── geospatial-function.test.ts   (teste geo isolado)
    ├── multi-search-mapper.test.ts   (teste mapper)
    ├── multi-search-schema-awareness.test.ts (teste schema awareness)
    ├── index.test.ts                 (teste original)
    └── schema-awareness.test.ts      (teste mapper original)

src/prisma-generic-search-service/
├── index.ts                          (arquivo original + exports)
├── multi-search-service.ts          (service novo)
└── tests/
    ├── multi-search-service.test.ts  (teste service)
    ├── integration-complete.test.ts  (teste integração)
    ├── prisma-generic-search-service.test.ts (teste original)
    └── prisma-logs.test.ts           (teste original)
```

## 🚀 **FORMATO DE USO**

### **Opção 1: Sem Schema (compatibilidade)**
```typescript
// 1. Frontend Request (novo formato)
const request: MultiSearchRequest = {
  include: ['list', 'map', 'meta'],
  list: {
    fields: ['id', 'title', 'price'],
    relations: { broker: true },
    pagination: { page: 1, limit: 10 }
  },
  map: {
    fields: ['id', 'latitude', 'longitude']
  },
  filters: {
    tipo: { value: 'Casa' },
    location: { 
      value: { 
        type: 'bbox', 
        bounds: { west: -51, south: -30, east: -50, north: -29 } 
      } 
    }
  }
}

// 2. Mapper: Frontend → Prisma (sem validação)
const mapper = MultiSearchMapper.createWithoutSchema()
const queries = mapper.mapMultiSearch(request)

// 3. Service: Transaction paralela
const service = new PrismaMultiService('property', prisma)
const result = await service.multiSearch(queries)

// 4. Response estruturada
console.log(result.list?.data)     // Lista paginada
console.log(result.map?.data)      // Dados do mapa
console.log(result.meta)           // Metadados globais
```

### **Opção 2: Com Schema Awareness (recomendado)**
```typescript
import { TEST_SCHEMA_WITH_GEO } from './multi-search-interfaces'

// 1. Schema de validação
const schema = TEST_SCHEMA_WITH_GEO // ou seu próprio schema

// 2. Mapper com validação
const mapper = MultiSearchMapper.createWithSchema(schema)

// 3. Request com validação automática
const request: MultiSearchRequest = {
  include: ['list', 'map'],
  list: {
    fields: ['id', 'title', 'tipo'], // ✅ Validados vs schema
    pagination: { page: 1, limit: 10 }
  },
  map: {
    fields: ['latitude', 'longitude'] // ✅ Validados vs schema
  },
  filters: {
    location: { // ✅ Validado vs geo-point no schema
      value: { 
        type: 'polygon',
        coordinates: [[-49.76, -29.18], [-50.87, -29.09], [-49.76, -29.18]]
      }
    }
  }
}

// 4. Execução com type safety
const queries = mapper.mapMultiSearch(request) // Valida campos automaticamente
const result = await service.multiSearch(queries)
```

### **Opção 3: Compatibilidade estática (para testes)**
```typescript
// Para manter testes existentes funcionando
const queries = MultiSearchMapper.mapMultiSearch(request)
```

## 🚨 **REGRAS CRÍTICAS DE USO**

### **⚠️ SCHEMA É OBRIGATÓRIO PARA ARRAYS**

**DESCOBERTA CRÍTICA:** `createSQLBuilder()` **DEVE** receber schema obrigatoriamente para detectar campos array corretamente.

#### **❌ ERRO COMUM:**
```typescript
// SEM SCHEMA = CAMPOS ARRAY NÃO FUNCIONAM
const sqlBuilder = createSQLBuilder() // ❌ SEM SCHEMA!
```

**Resultado:** Campo `operacao` (que é `string[]` no PostgreSQL) é tratado como string simples:
```sql
-- SQL INCORRETO gerado:
WHERE operacao = 'venda'  -- ❌ ERRO! Vai dar "malformed array literal"
```

#### **✅ SOLUÇÃO CORRETA:**
```typescript
import { createTestPropertySchema } from './filter/schema-adapter'

// ✅ SEMPRE PASSAR SCHEMA
const schema = createTestPropertySchema()
const sqlBuilder = createSQLBuilder({ schema })
```

**Resultado:** Campo `operacao` é corretamente detectado como array:
```sql
-- SQL CORRETO gerado:
WHERE 'venda' = ANY(operacao)  -- ✅ FUNCIONA! Detecta array via SSOT
```

#### **🔧 COMO APLICAR:**

**1. URL Parser Integration:**
```typescript
import { createSQLBuilder } from '../postgre-search-sql-builder'
import { createTestPropertySchema } from '../postgre-search-sql-builder/filter/schema-adapter'

// 🚨 OBRIGATÓRIO: Schema para detecção de arrays
const schema = createTestPropertySchema()
const sqlBuilder = createSQLBuilder({ schema })
```

**2. Examples e Database Testing:**
```typescript
// TODOS os examples e testes devem seguir este padrão
const schema = createTestPropertySchema()
const sqlBuilder = createSQLBuilder({ schema })

// Agora operacao, caracteristicas, tags (arrays) funcionam corretamente
```

#### **🔍 COMO IDENTIFICAR O PROBLEMA:**

**Sintomas:**
- Erro PostgreSQL: `malformed array literal: "venda"`
- SQL gerado: `operacao = 'venda'` em vez de `'venda' = ANY(operacao)`
- Filtros de array não funcionam

**Diagnóstico:**
- Verificar se `createSQLBuilder({ schema })` está sendo usado
- Confirmar se schema contém definição `string[]` para campos array

**Validação:**
```typescript
// Verificar se schema está sendo usado:
console.log(sqlBuilder.getStats().hasSchema) // deve ser true
```

## 🔥 **TROUBLESHOOTING COMUM**

### **Problema: "malformed array literal: 'venda'"**

**Causa:** `createSQLBuilder()` chamado sem schema parameter

**Sintoma:** 
```sql
WHERE operacao = 'venda'  -- Tenta inserir string em campo array
```

**Solução:**
```typescript
// ❌ ERRADO:
const sqlBuilder = createSQLBuilder()

// ✅ CORRETO:
const schema = createTestPropertySchema() 
const sqlBuilder = createSQLBuilder({ schema })
```

### **Problema: Arrays sendo tratados como strings**

**Causa:** FilterConverter sem informação SSOT sobre tipos de campo

**Diagnóstico:**
```typescript
// Verificar se campo está definido como array no schema:
const fieldInfo = schema.fields.find(f => f.name === 'operacao')
console.log(fieldInfo?.type) // deve ser 'string[]'
```

**Solução:** Garantir que schema define corretamente:
```typescript
{
  name: 'operacao',
  type: 'string[]',  // ✅ CRÍTICO: [] indica array
  db: 'operacao'
}
```