# Guard Helpers - Guia Completo

**Funções auxiliares para simplificar o uso da autenticação API v2**

## 📋 Índice

1. [Autenticação Básica](#autenticação-básica)
2. [Gestão de Tokens](#gestão-de-tokens)
3. [Login e Logout](#login-e-logout)
4. [Scripts JavaScript](#scripts-javascript)
5. [Manutenção e Limpeza](#manutenção-e-limpeza)
6. [Debug e Configuração](#debug-e-configuração)
7. [Exemplos Práticos](#exemplos-práticos)

## 👤 Autenticação Básica

### `authUser()`
Obtém o usuário atualmente autenticado.

```php
$user = authUser();
if ($user) {
    echo "Usuário: " . $user['nome'];
    echo "ID: " . $user['id'];
}
```

### `authCheck()`
Verifica se há um usuário autenticado.

```php
if (authCheck()) {
    echo "Usuário está logado";
} else {
    echo "Usuário não está logado";
}
```

### `authId()`
Obtém o ID do usuário atual.

```php
$userId = authId();
if ($userId) {
    echo "ID do usuário: " . $userId;
}
```

### `authCan(string $permission)`
Verifica se o usuário atual tem uma permissão específica.

```php
if (authCan('tickets:create')) {
    echo "Pode criar tickets";
}

if (authCan('admin:access')) {
    echo "É administrador";
}
```

## 🎫 Gestão de Tokens

### `spaToken(?int $userId, string $name, bool $reuseExisting)`
Cria ou obtém token SPA existente.

```php
// Token para usuário atual (reutiliza se válido)
$token = spaToken();

// Token para usuário específico
$token = spaToken(123, 'mobile-app');

// Sempre criar novo (não reutilizar)
$token = spaToken(123, 'api-token', false);

if ($token) {
    echo "Token: " . $token->getPlainTextToken();
    echo "Expira em: " . $token->getExpiresAt();
}
```

### `webToken(string $name)`
Token otimizado para web (evita spam de F5).

```php
// Para usar em templates/views
$token = webToken('web-session');
if ($token) {
    echo "<script>window.token = '{$token}';</script>";
}
```

### `currentToken()`
Obtém o token atual sendo usado na requisição.

```php
$token = currentToken();
if ($token) {
    echo "Token atual: " . $token->getName();
    echo "Habilidades: " . implode(', ', $token->getAbilities());
}
```

### `tokenCan(string $ability)`
Verifica se o token atual tem uma habilidade específica.

```php
if (tokenCan('users:read')) {
    echo "Token pode ler usuários";
}

if (tokenCan('*')) {
    echo "Token tem acesso completo";
}
```

### `createApiToken(int $userId, string $name, array $abilities, ?int $expiresIn)`
Cria token API com configurações específicas.

```php
// Token básico
$token = createApiToken(123, 'integration-api');

// Token com habilidades limitadas
$token = createApiToken(123, 'mobile-app', ['tickets:read', 'users:profile']);

// Token com expiração (7 dias)
$token = createApiToken(123, 'temp-access', ['*'], 7 * 24 * 60);

echo "Novo token: " . $token->getPlainTextToken();
```

## 🔐 Login e Logout

### `loginAttempt(string $username, string $password)`
Tenta fazer login com credenciais.

```php
$user = loginAttempt('joao', 'senha123');
if ($user) {
    echo "Login bem-sucedido: " . $user['nome'];
} else {
    echo "Credenciais inválidas";
}
```

### `loginForSpa(string $username, string $password)`
Login que retorna token SPA automaticamente.

```php
$token = loginForSpa('joao', 'senha123');
if ($token) {
    echo "Login SPA bem-sucedido";
    echo "Token: " . $token->getPlainTextToken();
    
    // Definir cookie automaticamente
    setcookie('spa_token', $token->getPlainTextToken(), time() + 86400);
} else {
    echo "Login falhou";
}
```

### `guardLogout()`
Faz logout do usuário atual (revoga token atual).

```php
if (guardLogout()) {
    echo "Logout bem-sucedido";
} else {
    echo "Erro no logout";
}
```

### `revokeToken()` / `revokeAllTokens()`
Revoga tokens específicos.

```php
// Revogar token atual
if (revokeToken()) {
    echo "Token atual revogado";
}

// Revogar todos os tokens do usuário
$revoked = revokeAllTokens();
echo "Revogados {$revoked} tokens";
```

## 📜 Scripts JavaScript

### `renderCookieAuthScript()` ⭐ **Recomendado**
Gera script para autenticação via cookie (sem tokens).

```php
<!-- Em qualquer view/template -->
<?php if (authCheck()): ?>
    <?= renderCookieAuthScript() ?>
    <div id="react-app"></div>
    
    <script>
        // window.OfficeGestAPI já está disponível
        console.log('Usuário:', window.OfficeGestAPI.user);
        
        // React pode usar imediatamente
        ReactDOM.render(<MyApp />, document.getElementById('react-app'));
    </script>
<?php endif; ?>
```

### `renderAuthScript(bool $includeToken, bool $reuseExistingToken)`
Script com controle de tokens.

```php
<!-- Sem token (só cookie) -->
<?= renderAuthScript(false) ?>

<!-- Com token reutilizado (evita F5 spam) -->
<?= renderAuthScript(true, true) ?>

<!-- Com token sempre novo -->
<?= renderAuthScript(true, false) ?>
```

### `generateAuthScript()` / `generateCookieAuthScript()`
Versões que retornam só o JavaScript (sem tags `<script>`).

```php
$jsCode = generateCookieAuthScript();
file_put_contents('auth-config.js', $jsCode);

// Ou inline em templates
echo "<script type='module'>";
echo generateAuthScript(true, true);
echo "</script>";
```

## 🧹 Manutenção e Limpeza

### `userTokens(?int $userId)`
Lista todos os tokens de um usuário.

```php
// Tokens do usuário atual
$tokens = userTokens();

// Tokens de usuário específico
$tokens = userTokens(123);

foreach ($tokens as $token) {
    echo "Token: " . $token->getName();
    echo "Criado: " . $token->getCreatedAt();
    echo "Expira: " . $token->getExpiresAt();
    echo "---\n";
}
```

### `cleanupUserTokens(int $userId, int $keepCount, ?string $tokenName)`
Limpa tokens antigos (mantém só os N mais recentes).

```php
// Manter só os 3 tokens mais recentes
$removed = cleanupUserTokens(123, 3);
echo "Removidos {$removed} tokens antigos";

// Limpar só tokens web-session
$removed = cleanupUserTokens(123, 2, 'web-session');

// Em cron job para todos os usuários
$users = getAllActiveUsers(); // sua lógica
foreach ($users as $user) {
    cleanupUserTokens($user['id'], 5);
}
```

### `pruneTokens()`
Remove todos os tokens expirados do sistema.

```php
// Em cron job diário
$removed = pruneTokens();
echo "Removidos {$removed} tokens expirados";
```

## 🐛 Debug e Configuração

### `guardDebug()`
Informações completas do estado atual.

```php
$debug = guardDebug();
echo "<pre>" . print_r($debug, true) . "</pre>";

// Exemplo de saída:
// Array (
//     [authenticated] => 1
//     [user] => Array ( [id] => 123, [name] => João )
//     [current_token] => Array ( [name] => web-session, [abilities] => ['*'] )
//     [total_user_tokens] => 3
//     [config] => Array ( [spa_expires_in] => 1440 )
// )
```

### `guardConfig(string $key, $default)`
Acessa configurações do Guard.

```php
$spaExpires = guardConfig('spa.expires_in', 1440);
$cookieName = guardConfig('spa.cookie_name', 'guard_token');
$maxTokens = guardConfig('security.max_tokens_per_user', 50);

echo "SPA expira em: {$spaExpires} minutos";
```

## 💡 Exemplos Práticos

### 1. View com React Injetado
```php
<?php if (authCheck()): ?>
    <!-- Inicialização automática sem F5 spam -->
    <?= renderCookieAuthScript() ?>
    
    <div class="user-info">
        <strong>Usuário:</strong> <?= authUser()['nome'] ?>
    </div>
    
    <div id="react-tickets-widget"></div>
    
    <script type="text/babel">
        function TicketsWidget() {
            const [tickets, setTickets] = React.useState([]);
            
            const loadTickets = async () => {
                const response = await fetch('/api/v2/tickets', {
                    credentials: 'include',
                    headers: window.OfficeGestAPI.defaultHeaders
                });
                setTickets(await response.json());
            };
            
            return (
                <div>
                    <button onClick={loadTickets}>Carregar Tickets</button>
                    {tickets.map(ticket => <div key={ticket.id}>{ticket.title}</div>)}
                </div>
            );
        }
        
        ReactDOM.render(<TicketsWidget />, document.getElementById('react-tickets-widget'));
    </script>
<?php else: ?>
    <div class="alert alert-warning">
        <a href="/login">Fazer Login</a>
    </div>
<?php endif; ?>
```

### 2. Endpoint de Login Custom
```php
// Em algum controller
public function customLogin()
{
    $username = $_POST['username'] ?? '';
    $password = $_POST['password'] ?? '';
    
    $token = loginForSpa($username, $password);
    
    if ($token) {
        // Login bem-sucedido
        return json_encode([
            'success' => true,
            'user' => authUser(),
            'token' => $token->getPlainTextToken(),
            'expires_at' => $token->getExpiresAt()
        ]);
    } else {
        return json_encode([
            'success' => false,
            'error' => 'Credenciais inválidas'
        ]);
    }
}
```

### 3. Middleware de API
```php
// Verificar permissões em endpoints
public function apiMiddleware($permission = null)
{
    if (!authCheck()) {
        http_response_code(401);
        echo json_encode(['error' => 'Not authenticated']);
        exit;
    }
    
    if ($permission && !authCan($permission)) {
        http_response_code(403);
        echo json_encode(['error' => 'Permission denied']);
        exit;
    }
    
    if (!tokenCan('api:access')) {
        http_response_code(403);
        echo json_encode(['error' => 'Token without API access']);
        exit;
    }
    
    // Continuar...
}
```

### 4. Cron Job de Limpeza
```php
// Script de manutenção (executar diariamente)
<?php
require_once 'bootstrap.php';

echo "=== Limpeza de Tokens ===\n";

// 1. Remover tokens expirados
$expired = pruneTokens();
echo "Tokens expirados removidos: {$expired}\n";

// 2. Limpar tokens antigos por usuário
$users = getUsersWithManyTokens(); // sua lógica
foreach ($users as $user) {
    $removed = cleanupUserTokens($user['id'], 5);
    if ($removed > 0) {
        echo "Usuário {$user['id']}: {$removed} tokens removidos\n";
    }
}

// 3. Relatório final
$totalTokens = getTotalActiveTokens(); // sua lógica
echo "Total de tokens ativos: {$totalTokens}\n";
?>
```

### 5. Dashboard de Tokens
```php
<?php if (authCan('admin:tokens')): ?>
    <div class="tokens-admin">
        <h3>Gestão de Tokens - <?= authUser()['nome'] ?></h3>
        
        <?php $tokens = userTokens(); ?>
        <p>Total de tokens: <?= count($tokens) ?></p>
        
        <table class="table">
            <thead>
                <tr><th>Nome</th><th>Criado</th><th>Último Uso</th><th>Expira</th><th>Ações</th></tr>
            </thead>
            <tbody>
                <?php foreach ($tokens as $token): ?>
                <tr>
                    <td><?= $token->getName() ?></td>
                    <td><?= $token->getCreatedAt() ?></td>
                    <td><?= $token->getLastUsedAt() ?></td>
                    <td><?= $token->getExpiresAt() ?: 'Nunca' ?></td>
                    <td>
                        <button onclick="revokeToken(<?= $token->getId() ?>)">
                            Revogar
                        </button>
                    </td>
                </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
        
        <button onclick="createNewToken()">Criar Token API</button>
        <button onclick="cleanupOldTokens()">Limpar Antigos</button>
    </div>
    
    <script>
    async function createNewToken() {
        const name = prompt('Nome do token:');
        if (name) {
            const response = await fetch('/api/v2/tokens', {
                method: 'POST',
                credentials: 'include',
                headers: window.OfficeGestAPI.defaultHeaders,
                body: JSON.stringify({ name })
            });
            
            if (response.ok) {
                location.reload();
            }
        }
    }
    </script>
<?php endif; ?>
```

## ⚡ Dicas de Performance

1. **Use `renderCookieAuthScript()`** para React/SPA - evita tokens desnecessários
2. **`spaToken()` reutiliza** tokens válidos automaticamente (evita F5 spam)
3. **Configure limpeza automática** via cron job
4. **Use `cleanupUserTokens()`** para usuários com muitos tokens
5. **`guardDebug()`** só em desenvolvimento

## 🎯 Resumo de Uso

| Cenário | Helper Recomendado |
|---------|-------------------|
| React injetado | `renderCookieAuthScript()` |
| API externa | `createApiToken()` |
| Login SPA | `loginForSpa()` |
| Verificar usuário | `authCheck()` + `authUser()` |
| Verificar permissões | `authCan()` + `tokenCan()` |
| Manutenção | `pruneTokens()` + `cleanupUserTokens()` |
| Debug | `guardDebug()` |

Estes helpers tornam o uso do Guard **extremamente simples** e cobrem todos os casos de uso comuns! 🚀