# 🔔 Notificações em Tempo Real para Aprovação de Compras

## 📋 Resumo

Implementado sistema de notificações em tempo real para que clientes recebam notificações instantâneas quando suas compras são aprovadas ou rejeitadas.

---

## ✅ Implementação

### **1. Notificação de Compra Aprovada**

Quando uma compra é **aprovada (confirmada)**, o cliente recebe uma notificação em tempo real via WebSocket.

**Dados da Notificação:**
```json
{
  "type": "purchase_approved",
  "title": "Compra Aprovada! 🎉",
  "message": "Sua compra de 150.50 MZN foi aprovada!",
  "data": {
    "purchase_id": 123,
    "purchase_code": "COMPRA_1234567890_ABC123",
    "purchase_amount": 150.50,
    "points_earned": 30,
    "total_points": 250,
    "establishment_name": "Restaurante Sabor",
    "confirmed_at": "2024-01-15T10:30:00Z",
    "confirmed_by": 5
  },
  "timestamp": "2024-01-15T10:30:00Z"
}
```

---

### **2. Notificação de Compra Rejeitada**

Quando uma compra é **rejeitada**, o cliente recebe uma notificação em tempo real via WebSocket.

**Dados da Notificação:**
```json
{
  "type": "purchase_rejected",
  "title": "Compra Rejeitada",
  "message": "Sua compra de 200.00 MZN foi rejeitada.",
  "data": {
    "purchase_id": 124,
    "purchase_code": "COMPRA_1234567890_XYZ789",
    "purchase_amount": 200.00,
    "rejection_reason": "Valor não confere com o recibo",
    "establishment_name": "Restaurante Sabor"
  },
  "timestamp": "2024-01-15T10:35:00Z"
}
```

---

## 🔌 Como o Cliente Recebe Notificações

### **1. Conectar ao WebSocket**

O cliente precisa se conectar ao Socket.io:

```javascript
import io from 'socket.io-client';

const socket = io('http://localhost:8000', {
  transports: ['websocket'],
  auth: {
    token: 'Bearer YOUR_JWT_TOKEN' // Token de autenticação
  }
});
```

---

### **2. Registrar Usuário Online**

Após conectar, registrar o usuário:

```javascript
socket.on('connect', () => {
  console.log('Conectado ao servidor');
  
  // Registrar usuário online usando user_id
  socket.emit('user-online', userId); // userId do usuário autenticado
});

socket.on('connected', (data) => {
  console.log('Registrado:', data.message);
});
```

---

### **3. Escutar Notificações**

Escutar eventos de notificação:

```javascript
// Escutar notificações de compras aprovadas/rejeitadas
socket.on('notification', (notificationData) => {
  console.log('Nova notificação:', notificationData);
  
  if (notificationData.type === 'purchase_approved') {
    // Exibir notificação de compra aprovada
    showNotification({
      title: notificationData.title,
      message: notificationData.message,
      type: 'success',
      data: notificationData.data
    });
    
    // Atualizar pontos na UI
    updatePoints(notificationData.data.total_points);
    
    // Atualizar lista de compras
    refreshPurchases();
  } else if (notificationData.type === 'purchase_rejected') {
    // Exibir notificação de compra rejeitada
    showNotification({
      title: notificationData.title,
      message: notificationData.message,
      type: 'error',
      data: notificationData.data
    });
    
    // Atualizar lista de compras
    refreshPurchases();
  }
});
```

---

## 📊 Fluxo de Notificação

### **Aprovação de Compra:**

```
1. Admin/Estabelecimento aprova compra
   POST /api/purchases/:id/confirm
   ↓
2. Sistema confirma compra no banco
   - Atualiza status para 'confirmed'
   - Adiciona pontos à carteira
   - Registra histórico
   ↓
3. Sistema busca dados do estabelecimento e pontos
   ↓
4. Sistema envia notificação via Socket.io
   - Busca socket do cliente (user_id)
   - Se cliente estiver conectado, envia notificação
   - Se não estiver conectado, notificação é perdida
   ↓
5. Cliente recebe notificação em tempo real
   - Exibe notificação na tela
   - Atualiza pontos na UI
   - Atualiza lista de compras
```

---

## 🔧 Arquivos Modificados

### **1. `utils/notificationUtils.js`**
- ✅ Criada função `sendPurchaseApprovedNotification()`
- ✅ Criada função `sendPurchaseRejectedNotification()`
- ✅ Função genérica `sendNotification()`
- ✅ Integração com `userSocketMap`

### **2. `controllers/purchaseController.js`**
- ✅ `confirmPurchase` - Envia notificação quando compra é aprovada
- ✅ `rejectPurchase` - Envia notificação quando compra é rejeitada
- ✅ Busca dados completos para notificação (estabelecimento, pontos)

### **3. `middleware/websocketHandler.js`**
- ✅ Evento `user-online` - Registra usuário conectado
- ✅ Evento `subscribe-purchase-notifications` - Inscrição específica para notificações de compras
- ✅ Evento `connected` - Confirmação de conexão

---

## 📝 Exemplo de Implementação no Frontend

### **React/Flutter/React Native:**

```javascript
// Conectar ao WebSocket
const socket = io('http://localhost:8000');

// Quando conectar
socket.on('connect', () => {
  // Registrar usuário (user_id do usuário autenticado)
  socket.emit('user-online', currentUserId);
});

// Escutar notificações
socket.on('notification', (notification) => {
  if (notification.type === 'purchase_approved') {
    // Exibir notificação
    showSuccessNotification({
      title: 'Compra Aprovada! 🎉',
      message: `Você ganhou ${notification.data.points_earned} pontos!`,
      duration: 5000
    });
    
    // Atualizar pontos
    setUserPoints(notification.data.total_points);
    
    // Atualizar lista de compras
    refreshPurchases();
  } else if (notification.type === 'purchase_rejected') {
    // Exibir notificação de rejeição
    showErrorNotification({
      title: 'Compra Rejeitada',
      message: notification.data.rejection_reason,
      duration: 5000
    });
    
    // Atualizar lista de compras
    refreshPurchases();
  }
});
```

---

## 🎯 Casos de Uso

### **Cenário 1: Cliente Está Online**
1. ✅ Compra é aprovada pelo admin
2. ✅ Sistema detecta que cliente está conectado
3. ✅ Notificação é enviada imediatamente
4. ✅ Cliente vê notificação em tempo real
5. ✅ Pontos são atualizados na UI instantaneamente

### **Cenário 2: Cliente Está Offline**
1. ✅ Compra é aprovada pelo admin
2. ✅ Sistema detecta que cliente não está conectado
3. ✅ Notificação não é enviada (perdida)
4. ✅ Cliente verá atualização ao abrir o app (próxima requisição)

### **Cenário 3: Múltiplos Dispositivos**
1. ✅ Cliente conectado em 2 dispositivos
2. ✅ Compra é aprovada
3. ✅ Ambos dispositivos recebem notificação
4. ✅ Ambos dispositivos atualizam em tempo real

---

## ⚙️ Implementação Técnica

### **Backend (Node.js/Express):**

```javascript
// Em confirmPurchase
const confirmedPurchase = await Purchase.confirm(id, confirmedBy);

// Buscar dados completos
const establishmentName = ...;
const walletPoints = ...;

// Enviar notificação
const io = req.app.locals.io;
if (io) {
    sendPurchaseApprovedNotification(
        String(confirmedPurchase.user_id),
        {
            purchase_id: confirmedPurchase.purchase_id,
            purchase_amount: confirmedPurchase.purchase_amount,
            points_earned: confirmedPurchase.points_earned,
            total_points: walletPoints,
            establishment_name: establishmentName
        }
    );
}
```

---

## ✅ Benefícios

1. ✅ **Tempo Real**: Cliente recebe notificação instantaneamente
2. ✅ **Experiência Melhor**: Cliente vê pontos atualizados sem recarregar
3. ✅ **Transparência**: Cliente sabe imediatamente se compra foi aprovada/rejeitada
4. ✅ **Engajamento**: Cliente fica mais engajado sabendo que ganhou pontos
5. ✅ **Feedback Imediato**: Cliente recebe feedback imediato sobre suas compras

---

## 🔍 Verificação

Para verificar se está funcionando:

1. **Cliente conecta ao WebSocket:**
   ```javascript
   socket.emit('user-online', userId);
   ```

2. **Admin aprova compra:**
   ```bash
   POST /api/purchases/123/confirm
   ```

3. **Cliente recebe notificação:**
   ```javascript
   socket.on('notification', (data) => {
     console.log('Notificação recebida:', data);
   });
   ```

---

## 📊 Estrutura da Notificação

### **Notificação de Compra Aprovada:**
```typescript
interface PurchaseApprovedNotification {
  type: 'purchase_approved';
  title: string;
  message: string;
  data: {
    purchase_id: number;
    purchase_code: string;
    purchase_amount: number;
    points_earned: number;
    total_points: number;
    establishment_name: string;
    confirmed_at: string;
    confirmed_by: number;
  };
  timestamp: string;
}
```

### **Notificação de Compra Rejeitada:**
```typescript
interface PurchaseRejectedNotification {
  type: 'purchase_rejected';
  title: string;
  message: string;
  data: {
    purchase_id: number;
    purchase_code: string;
    purchase_amount: number;
    rejection_reason: string;
    establishment_name: string;
  };
  timestamp: string;
}
```

---

## 🔒 Segurança

- ✅ Notificações são enviadas **apenas para o cliente** que fez a compra
- ✅ Verificação de conexão antes de enviar
- ✅ Cliente precisa estar autenticado para se conectar
- ✅ Logs de todas as notificações enviadas

---

## ⚠️ Limitações

1. **Cliente Offline**: Se cliente não estiver conectado, notificação é perdida
2. **Conexão Perdida**: Se conexão cair, cliente não recebe notificação
3. **Múltiplos Dispositivos**: Cada dispositivo precisa se conectar separadamente

### **Soluções Futuras:**

1. **Sistema de Notificações Push** (Firebase, OneSignal)
2. **Fila de Notificações** (Redis, Bull)
3. **Persistência de Notificações** (tabela `notifications`)

---

## 📝 Notas Importantes

- ✅ Notificações são enviadas **após** a aprovação ser processada
- ✅ Se notificação falhar, a aprovação ainda é processada (não interrompe)
- ✅ Logs são registrados para debug e auditoria
- ✅ Sistema é resiliente (não quebra se WebSocket falhar)




