# ⚙️ Manual Técnico & Arquitetura de Software — OmniFinder Pro B2B

Este documento contém a **especificação técnica detalhada, arquitetura de código, APIs REST, pipelines de dados e regras de negócio** do **OmniFinder**, produto da **JotaTek.ia**.

---

## 📌 Índice Técnico

1. [Arquitetura Geral do Sistema](#1-arquitetura-geral-do-sistema)
2. [Estratégia de Scraping & Fallback Resiliente](#2-estratégia-de-scraping--fallback-resiliente)
3. [Estrutura de Diretórios e Módulos](#3-estrutura-de-diretórios-e-módulos)
4. [Especificação Completa das APIs REST (Endpoints)](#4-especificação-completa-das-apis-rest-endpoints)
5. [Algoritmo de Deduplicação & Extratores Regex](#5-algoritmo-de-deduplicação--extratores-regex)
6. [Motor Duplo de Qualificação Comercial (Scoring Logic)](#6-motor-duplo-de-qualificação-comercial-scoring-logic)
7. [Módulo de Exportação Excel (OpenPyXL)](#7-módulo-de-exportação-excel-openpyxl)
8. [Instalação, Dependências e Comandos](#8-instalação-dependências-e-comandos)

---

## 1. Arquitetura Geral do Sistema

O OmniFinder foi desenvolvido em **Python 3**, utilizando o padrão **Application Factory** com **Flask** na camada web e **Playwright Async** na camada de automação headless.

```mermaid
graph TD
    ClientWeb["🌐 Dashboard Web (Glassmorphism / Leaflet.js)"]
    ClientCLI["💻 Terminal CLI (prospecta.py)"]
    
    subgraph Core Engine ["⚡ OmniFinder Core Engine"]
        FlaskServer["Flask App (server.py / app/api/routes.py)"]
        Dedup["Deduplicador (app/core/dedup.py)"]
        Scoring["Motor de Scoring (app/core/scoring.py)"]
        Extractors["Extratores Regex (app/core/extractors.py)"]
    end
    
    subgraph Scrapers ["🔍 Scrapers & Análise Paralela"]
        PlacesAPI["Google Places API (app/scrapers/google_places.py)"]
        PlaywrightScraper["Playwright Chromium (app/scrapers/google_maps.py)"]
        HTTPScraper["Maps HTTP Fallback (app/scrapers/google_maps_http.py)"]
        SiteAnalyzer["Site Analyzer ThreadPool (app/scrapers/site_analyzer.py)"]
    end
    
    subgraph Storage ["📁 Persistência & Cache"]
        LocalCache["Cache JSON (data/cache/)"]
        CSVRepo["Repositório CSV / Excel (data/exports/)"]
    end

    ClientWeb -->|Requisições HTTP REST| FlaskServer
    ClientCLI -->|Invocação Direta| Dedup
    FlaskServer --> Dedup
    Dedup --> Scrapers
    Scrapers --> PlacesAPI
    Scrapers --> PlaywrightScraper
    Scrapers --> HTTPScraper
    Scrapers --> SiteAnalyzer
    SiteAnalyzer --> Extractors
    Scrapers --> Scoring
    Scoring --> Storage
    Storage --> LocalCache
    Storage --> CSVRepo
```

---

## 2. Estratégia de Scraping & Fallback Resiliente

O sistema aplica o padrão **Strategy / Pipeline** com mecanismos de fallback contra falhas ambientais e bloqueios de WAF/Cloudflare.

```mermaid
flowchart TD
    A["Início da Prospecção"] --> B{"Modo Selecionado?"}
    
    B -->|mode = 'api'| C["Google Places API New"]
    B -->|mode = 'scraping'| D{"Playwright / Chromium Disponível?"}
    
    C -->|Requisição JSON Oficial| H["Lista de Leads Brutos"]
    
    D -->|Sim| E["Automação Playwright Chromium Async"]
    D -->|Não / Erro| F["Google Maps HTTP Scraper (Requests + Cloudscraper)"]
    
    E -->|Scrape de Resultados| H
    F -->|Parsing HTML DOM| H
    
    H --> I["Deduplicação por Tríplice Chave"]
    I --> J["Filtro de Rating Mínimo"]
    J --> K["Site Analyzer Paralelo (ThreadPoolExecutor - 20 workers)"]
    
    K --> L["Inspeção HTTP (HTTPS, Responsividade, Copyright, E-mail, Redes)"]
    L --> M["Cálculo de Prioridade (Scoring Dual)"]
    M --> N["Gravação em Cache JSON & Exportação CSV / XLSX"]
    N --> O["Retorno HTTP JSON para Dashboard / CLI"]
```

---

## 3. Estrutura de Diretórios e Módulos

```
OmniFinder/
├── app/
│   ├── api/
│   │   ├── __init__.py
│   │   └── routes.py         # Blueprints e endpoints REST Flask
│   ├── core/
│   │   ├── __init__.py
│   │   ├── dedup.py          # Algoritmo de deduplicação por tríplice chave
│   │   ├── extractors.py     # Regex para contatos, E-mail, Instagram, Facebook e WhatsApp
│   │   ├── geocoding.py      # Geocodificação OpenStreetMap (Nominatim)
│   │   ├── license.py        # Módulo de validação de licenças
│   │   ├── models.py         # Dataclass oficial do Lead
│   │   └── scoring.py        # Motor de Scoring Dual (Modo Site vs Modo Produto B2B)
│   ├── exports/
│   │   ├── __init__.py
│   │   └── excel_exporter.py # Gerador de planilhas OpenPyXL estilizadas (.xlsx)
│   ├── scrapers/
│   │   ├── __init__.py
│   │   ├── google_maps.py    # Scraper Playwright Chromium Async
│   │   ├── google_maps_http.py # Scraper HTTP Fallback (Requests + Cloudscraper)
│   │   ├── google_places.py  # Cliente oficial da Google Places API New
│   │   ├── osm.py            # Módulo de integração OpenStreetMap
│   │   └── site_analyzer.py  # Análise de integridade web paralela (ThreadPoolExecutor)
│   └── storage/
│       ├── __init__.py
│       ├── cache.py          # Gerenciador de cache JSON (TTL 30 dias)
│       └── repositories.py   # Persistência em disco CSV/XLSX
├── data/
│   ├── cache/                # Arquivos JSON de cache por termo
│   ├── exports/              # Arquivos CSV e XLSX exportados
│   └── raw/                  # Logs e inspeções técnicas
├── docs/                     # Documentação técnica oficial (ARCHITECTURE, API, USAGE, SCORING)
├── static/                   # Estilos CSS (Glassmorphism Dark) e JS (app.js)
├── templates/                # Layout HTML da Dashboard (index.html com Leaflet.js)
├── prospecta.py              # Linha de comando (CLI)
├── server.py                 # Application Factory Flask (Entrypoint Web)
└── requirements.txt          # Dependências Python
```

---

## 4. Especificação Completa das APIs REST (Endpoints)

Todas as requisições da Dashboard Web comunicam-se com os endpoints servidos pelo Blueprint Flask em `app/api/routes.py`.

### Resumo das Rotas HTTP:

| Método | Endpoint | Descrição |
|---|---|---|
| `GET` | `/` | Servidor da página HTML da Dashboard Interativa (`index.html`) |
| `POST` | `/api/search` | Executa busca de leads, deduplicação, análise paralela e scoring |
| `GET` | `/api/history` | Retorna o histórico de relatórios CSV/XLSX gerados |
| `GET` | `/api/download` | Realiza o download direto de um arquivo exportado |
| `POST` | `/api/generate-copy` | Gera copy comercial de WhatsApp via IA (Gemini/Groq) ou Smart Template |
| `POST` | `/api/test-key` | Valida uma Google Places API Key |
| `GET` | `/api/geocode` | Executa geocodificação direta e reversa via OpenStreetMap Nominatim |
| `POST` | `/api/verify-license` | Valida chave de licença ativa no sistema |

---

### Endpoints em Detalhe:

#### 1. `POST /api/search`
Executa o fluxo completo de prospecção.

**Payload JSON de Requisição:**
```json
{
  "query": "Dentistas Petrolina PE",
  "max": 100,
  "min_rating": 3.5,
  "no_cache": false,
  "objetivo": "site",
  "mode": "scraping",
  "api_key": "",
  "lat": -9.3891,
  "lng": -40.5027,
  "radius_km": 10.0
}
```

**Resposta JSON (200 OK):**
```json
{
  "leads": [
    {
      "nome": "Clínica Odontológica Exemplo",
      "rating": 4.8,
      "reviews": 120,
      "telefone": "(87) 99999-9999",
      "site": "http://clinicaexemplo.com.br",
      "status": "SITE_OK",
      "prioridade": 10,
      "motivo": "Site seguro, responsivo e atualizado.",
      "has_whatsapp": true,
      "email": "contato@clinicaexemplo.com.br",
      "ig_link": "https://instagram.com/clinicaexemplo",
      "fb_link": "https://facebook.com/clinicaexemplo"
    }
  ],
  "summary": {
    "SITE_OK": 1,
    "SEM_SITE": 4
  },
  "filename": "leads_dentistas_petrolina_pe.csv",
  "count_before_dedup": 10,
  "count_after_dedup": 5
}
```

---

#### 2. `POST /api/generate-copy`
Gera 3 variações de copy de abordagem comercial para WhatsApp.

**Payload JSON de Requisição:**
```json
{
  "lead": {
    "nome": "Clínica Exemplo",
    "categoria": "Odontologia",
    "rating": 4.5,
    "reviews": 85,
    "status": "SEM_SITE",
    "motivo": "Sem site cadastrado no Maps",
    "endereco": "Petrolina - PE"
  },
  "seller_profile": "site",
  "api_key": "OPCIONAL_GEMINI_KEY",
  "groq_api_key": "OPCIONAL_GROQ_KEY"
}
```

**Resposta JSON (200 OK):**
```json
{
  "success": true,
  "source": "gemini",
  "copy": {
    "direta": "Olá, equipe da Clínica Exemplo! Vi que vocês possuem 4.5 estrelas no Google Maps, porém ainda não possuem um site oficial...",
    "consultiva": "Olá! Notei a excelência do trabalho da Clínica Exemplo em Petrolina. Gostaria de apresentar uma oportunidade para duplicar seus agendamentos...",
    "followup": "Olá! Tudo bem? Passando para acompanhar meu contato anterior sobre a estruturação da presença digital da Clínica Exemplo..."
  }
}
```

---

## 5. Algoritmo de Deduplicação & Extratores Regex

### A. Algoritmo de Deduplicação (`app/core/dedup.py`)
Para evitar leads duplicados na mesma busca, o sistema cria uma chave hash combinada baseada em:
1. **Nome Normalizado** (conversão para minúsculas, remoção de acentos e pontuações).
2. **Telefone Limpo** (apenas dígitos numéricos).
3. **Endereço Simplificado** (primeiros 20 caracteres do logradouro).

Se 2 ou mais registros compartilharem a mesma chave hash, apenas a entrada com dados mais completos (presença de site ou telefone) é mantida.

### B. Extratores Regex (`app/core/extractors.py`)
- **E-mail**: `r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'` (excluindo extensões de imagens como `.png`, `.jpg`).
- **Instagram**: `r'(?:https?://)?(?:www\.)?instagram\.com/([a-zA-Z0-9_.]+)'`
- **Facebook**: `r'(?:https?://)?(?:www\.)?facebook\.com/([a-zA-Z0-9_.]+)'`

---

## 6. Motor Duplo de Qualificação Comercial (Scoring Logic)

Localizado em `app/core/scoring.py`, o cálculo de pontuação altera suas regras de acordo com o parâmetro `objetivo`.

```mermaid
flowchart TD
    Start["Lead Processado"] --> CheckObj{"Qual o Objetivo?"}
    
    CheckObj -->|objetivo = 'site'| ModeSite["Modo Venda de Sites (Prioridade 10 a 100)"]
    CheckObj -->|objetivo = 'produto'| ModeB2B["Modo Produto B2B (Score 0 a 100)"]
    
    ModeSite --> RuleSite["SEM_SITE=100 | LINK_SOCIAL=95 | DOMINIO_PARKADO=92 | SITE_QUEBRADO=90 | SITE_RUIM=50 | SITE_OK=10"]
    ModeB2B --> RuleB2B["Popularidade (50) + Reputação (20) + Presença Web (20) + Contatos (10)"]
```

---

## 7. Módulo de Exportação Excel (OpenPyXL)

O módulo `app/exports/excel_exporter.py` constrói a planilha corporativa programaticamente:

- **Estilos Aplicados**: Fontes Segoe UI, gradientes Navy (`#1B365D`), bordas finas cinza (`#D9D9D9`).
- **Zimbro de Cores**: Linhas pares com fundo `#F8F9FA` e ímpares `#FFFFFF`.
- **Formatação Condicional de Status**:
  - `SITE ATIVO`: Fundo verde claro (`#E6F4EA`), texto verde escuro (`#137333`).
  - `APENAS REDES`: Fundo amarelo claro (`#FEF7E0`), texto marrom (`#B06000`).
  - `SEM SITE`: Fundo vermelho claro (`#FCE8E6`), texto vermelho escuro (`#C5221F`).

---

## 8. Instalação, Dependências e Comandos

### Dependências Python (`requirements.txt`):
```text
flask>=3.0.0
playwright>=1.40.0
requests>=2.31.0
cloudscraper>=1.2.71
openpyxl>=3.1.2
google-generativeai>=0.3.0
groq>=0.4.0
```

### Instalação no Ambiente:
```bash
# 1. Instalar dependências Python
pip install -r requirements.txt

# 2. Instalar o navegador Chromium headless do Playwright
playwright install chromium
```

### Execução em Modo Web:
```bash
python server.py
# Acesso local em: http://127.0.0.1:5000
```

### Execução em Modo CLI:
```bash
python prospecta.py "dentistas Petrolina PE" --max 100 --headless --min-rating 4.0 --objetivo site
```
