# @horizon-modules/property-model-v3

Sistema completo para modelagem de propriedades imobiliárias V3 com **atributos dinâmicos**, **validação Zod**, **profiling de dados** e **pipeline de desenvolvimento automatizado**.

## 📦 Instalação

```bash
npm install @horizon-modules/property-model-v3
# ou
pnpm add @horizon-modules/property-model-v3
```

## 🚀 Uso Básico

```typescript
import { 
  PropertyModel,
  PropertyModelSchema,
  validatePropertyModel,
  safeValidatePropertyModel,
  generateFakeProperty,
  PropertyModelJsonSchema
} from '@horizon-modules/property-model-v3';

// Exemplo de propriedade V3
const property: PropertyModel = {
  reference: "AP001_V3",
  title: "Apartamento Premium - 3 qtos, 150m²",
  description: "Apartamento moderno com acabamentos de primeira linha...",
  attributes: {
    tipo: "Apartamento",
    operacao: ["venda"],
    dormitorios: 3,
    banheiros: 2,
    area_util: 150,
    valor_venda: 850000,
    endereco_cidade: "São Paulo",
    endereco_bairro: "Vila Madalena"
  },
  media_assets: {
    images: [
      {
        full: "https://images.unsplash.com/photo-1560448204-e02f11c3d0e2?w=800&q=80",
        cover: true
      }
    ]
  },
  settings: {
    currency_unit: "BRL",
    area_unit: "m2",
    exibir_no_mapa: true
  }
};

// Validação com Zod
const validProperty = validatePropertyModel(property);

// Validação safe (nunca lança erro)
const result = safeValidatePropertyModel(property);
if (result.success) {
  console.log("Propriedade válida:", result.data);
} else {
  console.log("Erros:", result.error.issues);
}

// Gerar dados fake
const fakeProperty = generateFakeProperty("apartamento");
```

## 🏗️ Arquitetura PropertyModel V3

### Estrutura Principal

```typescript
interface PropertyModel {
  reference: string              // Código único
  title: string                 // Título da propriedade
  description: string           // Descrição detalhada
  attributes: Record<string, any>  // Atributos dinâmicos
  media_assets: MediaAssets     // Fotos, vídeos, tours
  settings?: SettingsFormat     // Configurações de formato
  updated_at?: string          // Data de atualização
}
```

### Sistema de Atributos Dinâmicos

O V3 substitui o array de atributos por um **objeto chave-valor** mais flexível:

```typescript
// V2 (antigo)
attributes: [
  { key: "dormitorios", value: 3 },
  { key: "valor_venda", value: 850000, unit: "BRL" }
]

// V3 (novo)  
attributes: {
  dormitorios: 3,
  valor_venda: 850000,
  endereco_cidade: "São Paulo",
  caracteristicas: ["Churrasqueira", "Piscina"]
}
```

**Benefícios do V3:**
- ✅ Acesso direto: `property.attributes.dormitorios`
- ✅ Menos verboso e mais legível
- ✅ Melhor performance em consultas
- ✅ Compatível com NoSQL (MongoDB, DynamoDB)
- ✅ Validação Zod nativa

### Media Assets

```typescript
interface MediaAssets {
  images?: ImageMedia[]         // Fotos do imóvel
  videos?: VideoMedia[]         // Vídeos (YouTube, Vimeo)
  virtual_tours?: VirtualTourMedia[]  // Tours 360°
  documents?: DocumentMedia[]   // PDFs, documentos
}

interface ImageMedia {
  full: string                  // URL da imagem completa
  md?: string                  // Versão 640x480
  sm?: string                  // Versão 320x240  
  cover?: boolean              // Se é imagem principal
}
```

## 🎨 Gerador de Dados Fake Avançado

Sistema baseado em **profiling de dados reais** do Arbo CRM com **20+ atributos por imóvel**:

```typescript
import { 
  generateFakeProperty,
  generateFakeProperties,
  generateFakePropertyByType,
  getAvailablePropertyTypes 
} from '@horizon-modules/property-model-v3';

// Gerar uma propriedade aleatória
const property = generateFakeProperty();

// Gerar 50 propriedades  
const properties = generateFakeProperties(50);

// Gerar tipo específico
const apartamento = generateFakePropertyByType("apartamento");
const casa = generateFakePropertyByType("casa");
const terreno = generateFakePropertyByType("terreno");

// Ver tipos disponíveis
console.log(getAvailablePropertyTypes());
// ["apartamento", "casa", "sobrado", "terreno", "comercial"]
```

### Características dos Dados Fake

- **📍 Localização brasileira**: 5 cidades + bairros reais
- **💰 Valores realistas**: Baseados em dados reais do Arbo CRM  
- **🏠 Atributos contextuais**: 20-30 atributos por tipo de imóvel
- **🖼️ Imagens Unsplash**: URLs funcionais categorizadas por tipo
- **⚡ Performance**: Baseado em profiling estatístico

### Exemplo de Propriedade Fake Gerada

```json
{
  "reference": "FAKE_APARTAMENTOS_001", 
  "title": "Apartamento Premium - 3 qtos, 150m², 3 vagas",
  "description": "Apartamento moderno com acabamentos de primeira linha...",
  "attributes": {
    "tipo": "Apartamento",
    "operacao": ["venda"],
    "dormitorios": 3,
    "banheiros": 2,
    "suites": 1,
    "vagas": 3,
    "area_util": 150,
    "area_total": 180,
    "valor_venda": 1200000,
    "valor_condominio": 800,
    "andar": 12,
    "endereco_cidade": "São Paulo",
    "endereco_estado": "SP", 
    "endereco_bairro": "Vila Madalena",
    "endereco_cep": "05414-000",
    "caracteristicas": ["Churrasqueira", "Piscina", "Academia"],
    "mobiliado": false,
    "aceita_pets": true,
    "portao_eletronico": true
  },
  "media_assets": {
    "images": [
      {
        "full": "https://images.unsplash.com/photo-1560448204-e02f11c3d0e2?w=800&q=80",
        "cover": true
      }
    ]
  }
}
```

## 📊 ProfilerService - Análise de Dados

Ferramenta para **análise estatística** de datasets PropertyModel:

```typescript
import { ProfilerService, profileProperties } from '@horizon-modules/property-model-v3';

// Análise de arquivos
const profiler = new ProfilerService({
  inputDir: './data/properties',
  outputDir: './output',
  fieldConfigs: {
    'attributes.endereco_cidade': { maxExamples: 50 },
    'attributes.caracteristicas': { maxExamples: 100 }
  }
});

const report = await profiler.profile();
console.log(report);
// {
//   "attributes.tipo": ["Casa", "Apartamento", "Terreno"],
//   "attributes.endereco_cidade": ["São Paulo", "Rio de Janeiro", ...],
//   "attributes.caracteristicas": ["Churrasqueira", "Piscina", ...]
// }

// Análise em memória
const inMemoryReport = await profileProperties(propertyArray);
```

**Características:**
- ✅ **Concatena arrays**: Arrays de strings viram lista única de valores
- ✅ **Objetos aninhados**: Analisa `attributes.endereco_cidade`
- ✅ **Configurável**: Controle de quantos exemplos por campo
- ✅ **Genérico**: Funciona com qualquer estrutura JSON

## 🎨 Property Customizer - Transformação Baseada em Regras

Sistema para aplicar transformações complexas em dados PropertyV3 através de regras declarativas:

```typescript
import { 
  PropertyCustomizer,
  type MapRules 
} from '@horizon-modules/property-model-v3';

// Definir regras de transformação
const mapRules: MapRules = {
  attributesRules: [
    {
      key: 'tipo',
      condition: { eq: 'Casa de Condomínio' },
      rules: [
        { fn: 'upsertAttr', key: 'tipo', value: 'Casa/Sobrado' },
        { fn: 'upsertAttr', key: 'subtipo', value: 'Casa' },
        { fn: 'addToArray', key: 'tags', value: 'em-condominio' }
      ]
    },
    {
      key: 'caracteristicas',
      condition: { has_any: ['Piscina'] },
      rules: [
        { fn: 'removeFromArray', key: 'caracteristicas', value: 'Piscina' },
        { fn: 'upsertAttr', key: 'piscina', value: true }
      ]
    }
  ]
};

// Aplicar transformações
const transformedProperty = PropertyCustomizer(property, mapRules);
```

### Actions Disponíveis

- **upsertAttr**: Criar/atualizar atributo
- **removeAttr**: Remover atributo  
- **addToArray**: Adicionar valores a array
- **removeFromArray**: Remover valores de array

### Condições Suportadas

- **Igualdade**: `eq`, `not_eq`
- **Arrays**: `has`, `has_any`, `not_has`
- **Numéricos**: `gt`, `gte`, `lt`, `lte`
- **Texto**: `contains`, `starts_with`, `ends_with`
- **Booleanos**: `is_true`, `is_false`
- **Existência**: `exists`, `not_exists`

### Tags na Description

O sistema processa automaticamente tags especiais na description:

```typescript
const property = {
  description: `Casa linda [[description-en]]Beautiful house[[/description-en]] 
[[custom-attributes]]
{
  "energia_solar": true,
  "classificacao": "A+"
}
[[/custom-attributes]]
Com vista para o mar`
};

// Após processamento:
// property.attributes.description_en = 'Beautiful house'
// property.attributes.energia_solar = true
// property.description = 'Casa linda Com vista para o mar'
```

## 🌐 ApiClientService - Cliente HTTP

Cliente para envio de dados PropertyModel para APIs externas:

```typescript
import { ApiClientService } from '@horizon-modules/property-model-v3';

const client = new ApiClientService({
  endpoint: 'https://api.imobiliaria.com/properties',
  headers: { 'Authorization': 'Bearer token' },
  batchSize: 10  // Processa 10 por vez
});

// Enviar uma propriedade
await client.sendProperty(property);

// Enviar múltiplas propriedades
await client.sendProperties([prop1, prop2, prop3]);

// Enviar de pasta com JSONs
await client.sendPropertiesFromDir('./data/fake-properties');
```

**Formatos suportados:**
- Array direto: `[prop1, prop2]`
- Formato data: `{ "data": [prop1, prop2] }`
- Categorizado: `{ "apartamentos": [prop1], "casas": [prop2] }`

## 🔒 Validação com Zod

Sistema robusto de validação em runtime:

```typescript
import { 
  PropertyModelSchema,
  validatePropertyModel,
  safeValidatePropertyModel 
} from '@horizon-modules/property-model-v3';

// Validação direta (lança erro se inválido)
const property = validatePropertyModel(unknownData);

// Validação safe (nunca lança erro)
const result = safeValidatePropertyModel(unknownData);
if (result.success) {
  console.log("✅ Válido:", result.data);
} else {
  console.log("❌ Erros:", result.error.issues);
}

// Schema customizado
const StrictSchema = PropertyModelSchema.extend({
  reference: z.string().min(5).max(20)
});
```

## 📋 JSON Schema Export

Schemas JSON para validação externa:

```typescript
import { 
  PropertyModelJsonSchema,
  PropertyTypeSchemaJson 
} from '@horizon-modules/property-model-v3';

// Usar com validadores JSON Schema
import Ajv from 'ajv';
const ajv = new Ajv();
const validate = ajv.compile(PropertyModelJsonSchema);

const isValid = validate(propertyData);
if (!isValid) {
  console.log(validate.errors);
}
```

## 🛠️ Scripts de Desenvolvimento

Pipeline completo para desenvolvimento de dados:

### Scripts Principais

```bash
# Baixar dados reais do Arbo CRM
npm run dev:download

# Baixar dados fake do pacote arbo-crm  
npm run dev:download-arbo-fake

# Converter dados Arbo para PropertyModel V3
npm run dev:convert

# Fazer profiling dos dados convertidos
npm run dev:profile

# Gerar dados fake baseados no profiling
npm run dev:fake

# Gerar mocks para testes
npm run dev:mocks

# Gerar JSON Schema
npm run dev:json-schema

# Testar JSON Schema
npm run dev:test-json-schema

# Pipeline completo
npm run dev:all
```

### Estrutura de Desenvolvimento

```
__dev__/
├── data/                           # Dados temporários (não commitados)
│   ├── arbo-downloads/            # Dados reais do Arbo CRM
│   ├── arbo-fake-data-output/     # Dados fake do arbo-crm package
│   ├── property-v3-converted/     # Dados convertidos para V3
│   ├── property-v3-profiling/     # Relatórios de profiling
│   ├── property-v3-fake-data-output/  # Dados fake gerados
│   ├── property-v3-mock-output/   # Mocks para testes
│   └── json-schema/               # JSON Schema gerado
├── scripts/                       # Scripts de desenvolvimento
│   ├── arbo-download-properties.ts    # Baixa dados do Arbo
│   ├── arbo-download-fake-data.ts     # Baixa fake data do arbo-crm
│   ├── arbo-convert-to-property-v3.ts # Converte para V3
│   ├── profile-properties.ts          # Faz profiling
│   ├── generate-fake-data.ts          # Gera dados fake
│   ├── generate-mocks.ts              # Gera mocks
│   ├── generate-json-schema.ts        # Gera JSON Schema
│   └── test-json-schema.ts            # Testa JSON Schema
├── services/                      # Serviços de desenvolvimento
│   └── MockGeneratorService.ts        # Gerador de mocks
└── tests/                         # Testes dos serviços dev
    └── MockGeneratorService.test.ts
```

### Fluxo de Desenvolvimento

1. **🔄 Download**: `dev:download` → Baixa dados reais do Arbo CRM
2. **📊 Profiling**: `dev:profile` → Analisa padrões estatísticos nos dados
3. **🎨 Fake Data**: `dev:fake` → Gera dados fake baseados no profiling
4. **🧪 Mocks**: `dev:mocks` → Gera mocks para testes unitários
5. **📋 Schema**: `dev:json-schema` → Gera JSON Schema para validação externa

## 🏠 Modelo de Atributos

Sistema com **96 atributos pré-definidos** em 8 categorias:

```typescript
import { PropertyAttributesModel } from '@horizon-modules/property-model-v3';

// Ver todos os atributos disponíveis
console.log(PropertyAttributesModel.length); // 96

// Atributos por categoria
const comerciais = PropertyAttributesModel.filter(attr => attr.cat === "comercial");
const valores = PropertyAttributesModel.filter(attr => attr.cat === "valores");
const dependencias = PropertyAttributesModel.filter(attr => attr.cat === "dependencias");

// Buscar atributo específico
const dormitorios = PropertyAttributesModel.find(attr => attr.key === "dormitorios");
console.log(dormitorios);
// { key: "dormitorios", label: "Dormitórios", type: "Number", cat: "dependencias" }
```

### Categorias de Atributos

1. **comercial** (8): `operacao`, `status_comercial`, `financiavel`, `aceita_permuta`
2. **valores** (12): `valor_venda`, `valor_locacao`, `valor_condominio`, `valor_iptu`
3. **situacoes** (6): `disponivel`, `reservado`, `vendido`, `alugado`
4. **localizacao** (15): `endereco_cidade`, `endereco_bairro`, `latitude`, `longitude`
5. **estrutura** (20): `tipo`, `subtipo`, `area_total`, `area_util`, `conservacao`
6. **dependencias** (8): `dormitorios`, `banheiros`, `suites`, `vagas`
7. **caracteristicas** (15): `mobiliado`, `aceita_pets`, `churrasqueira`, `piscina`
8. **corretor** (12): `corretor_nome`, `corretor_telefone`, `corretor_email`

## 🔧 Utilitários

```typescript
import { 
  verifyAttrKeyInPropertyV3Model,
  mergePropertyAttributesModel,
  sortAttributes,
  preparaAttrValueLabel,
  unitListModel,
  formatListModel
} from '@horizon-modules/property-model-v3';

// Verificar se atributo existe
const attr = verifyAttrKeyInPropertyV3Model("dormitorios");

// Mesclar modelos de atributos
const customModel = mergePropertyAttributesModel(
  PropertyAttributesModel,
  [{ key: "piscina", label: "Piscina", type: "Boolean" }]
);

// Formatar labels de arrays
preparaAttrValueLabel(["venda", "locacao"]);
// Retorna: "venda e locacao"

// Unidades disponíveis
console.log(unitListModel.currency); // [{ key: "BRL", label: "R$" }]
console.log(unitListModel.area);     // [{ key: "m2", label: "m²" }]
```

## 🧪 Testes

```bash
# Executar todos os testes
npm run test

# Testes com cobertura
npm run test:coverage

# Testes dos serviços de desenvolvimento
npm run dev:test

# Verificação de tipos
npm run typecheck

# Build
npm run build
```

## 📈 Exemplo Completo

```typescript
import { 
  generateFakeProperties,
  ProfilerService,
  ApiClientService,
  validatePropertyModel
} from '@horizon-modules/property-model-v3';

async function exemploCompleto() {
  // 1. Gerar 100 propriedades fake
  console.log('🎨 Gerando dados fake...');
  const properties = generateFakeProperties(100);
  
  // 2. Validar todas as propriedades
  console.log('🔍 Validando propriedades...');
  const validProperties = properties.filter(prop => {
    try {
      validatePropertyModel(prop);
      return true;
    } catch {
      return false;
    }
  });
  
  console.log(`✅ ${validProperties.length}/${properties.length} propriedades válidas`);
  
  // 3. Fazer profiling dos dados
  console.log('📊 Fazendo profiling...');
  const profiler = new ProfilerService({ inputData: validProperties });
  const report = await profiler.profile();
  
  console.log('Tipos encontrados:', report['attributes.tipo']);
  console.log('Cidades encontradas:', report['attributes.endereco_cidade']);
  
  // 4. Enviar para API (exemplo)
  const client = new ApiClientService({
    endpoint: 'https://api.exemplo.com/properties',
    batchSize: 5
  });
  
  console.log('🚀 Enviando para API...');
  await client.sendProperties(validProperties.slice(0, 10));
  
  console.log('🎉 Processo concluído!');
}

exemploCompleto().catch(console.error);
```

## 🚀 Integração com Arbo CRM

O projeto integra nativamente com o `@horizon-modules/arbo-crm-integration`:

```typescript
// Os scripts de desenvolvimento usam o arbo-crm-integration
// para baixar dados reais e convertê-los para PropertyModel V3

// Dados reais → Profiling → Fake data realista
// Este processo garante que os dados fake sejam baseados
// em dados reais do mercado imobiliário brasileiro
```

## 📦 Exports Principais

```typescript
// Modelos e Tipos
export type { PropertyModel, MediaAssets, SettingsFormat }

// Schemas Zod
export { PropertyModelSchema, validatePropertyModel, safeValidatePropertyModel }

// JSON Schemas
export { PropertyModelJsonSchema, PropertyTypeSchemaJson }

// Gerador de Dados Fake
export { generateFakeProperty, generateFakeProperties, generateFakePropertyByType }

// Serviços
export { ProfilerService, ApiClientService }

// Property Customizer
export { PropertyCustomizer }
export type { PropertyV3, MapRules, AttributeRule, CustomAction }

// Modelo de Atributos
export { PropertyAttributesModel, unitListModel, formatListModel }

// Utilitários
export { verifyAttrKeyInPropertyV3Model, mergePropertyAttributesModel, sortAttributes }
```

## 🔄 Migração do V2 para V3

### Principais Mudanças

1. **Atributos**: Array → Objeto chave-valor
2. **Media**: `media` → `media_assets` com estrutura tipada
3. **Validação**: Zod schemas obrigatórios
4. **Settings**: Novo campo para configurações de formato

### Exemplo de Migração

```typescript
// V2
const propertyV2 = {
  reference: "AP001",
  attributes: [
    { key: "dormitorios", value: 3 },
    { key: "valor_venda", value: 850000, unit: "BRL" }
  ],
  media: {
    pictures: ["foto1.jpg", "foto2.jpg"]
  }
};

// V3
const propertyV3 = {
  reference: "AP001", 
  title: "Apartamento 3 dormitórios",
  description: "Descrição do imóvel...",
  attributes: {
    dormitorios: 3,
    valor_venda: 850000
  },
  media_assets: {
    images: [
      { full: "foto1.jpg", cover: true },
      { full: "foto2.jpg", cover: false }
    ]
  },
  settings: {
    currency_unit: "BRL",
    area_unit: "m2"
  }
};
```

---

## 📄 Licença

MIT - veja [LICENSE](LICENSE) para detalhes.

**Desenvolvido pela Horizon Modules** 🏗️