# client

Classe responsável pela autenticação OAuth 2.0 e Basic para envio de e-mail no Protheus. Encapsula o ciclo de vida do token (obtenção, refresh e consentimento) e o gerenciamento da conexão SMTP, com base nas tabelas `SYS_OAUTH_ACCOUNT` e `SYS_OAUTH_PROVIDER`.

## Atributos

| Atributo | Tipo | Descrição |
|---|---|---|
| `aScopes` | Array | Lista de scopes configurados para a requisição OAuth |
| `nEvent` | Numeric | Código do último evento registrado; valores negativos indicam erro |
| `cEventDesc` | Character | Descrição textual do último evento registrado |
| `cAliasAccount` | Character | Nome do alias da tabela de contas (`SYS_OAUTH_ACCOUNT`) |
| `cAliasProvider` | Character | Nome do alias da tabela de provedores (`SYS_OAUTH_PROVIDER`) |
| `cTenantId` | Character | Tenant ID descriptografado do provedor, quando aplicável |
| `lCliCredentials` | Logical | Indica se o fluxo de autenticação é `client_credentials` |
| `cAuthUrl` | Character | URL de autorização obtida do cadastro do provedor |

## Métodos

### new(cEmail)

Método construtor da classe. Inicializa os atributos internos, define os aliases das tabelas de conta e provedor, e chama `updateValues()` para carregar as configurações com base no e-mail informado.

| Parâmetro | Tipo | Descrição |
|---|---|---|
| `cEmail` | Character | E-mail da conta a ser utilizada; deve existir na tabela `SYS_OAUTH_ACCOUNT` |

**Retorno:** `Object` — instância da classe `client`.

**Exemplo:**
```advpl
Local oClient as object
oClient := totvs.framework.oauth.client():New("usuario@empresa.com")
```

---

### Destroy()

Método destruidor. Libera o array `aScopes` e o objeto `oMailManager` da memória e chama o destruidor da superclasse.

**Exemplo:**
```advpl
oClient:Destroy()
```

---

### SetScopes(aScopes)

Define os scopes de autenticação OAuth e os repassa à superclasse via `SetAuthOptions()`, concatenando-os no formato `scope=valor1,valor2`.

| Parâmetro | Tipo | Descrição |
|---|---|---|
| `aScopes` | Array | Lista de strings com os scopes a serem configurados |

**Exemplo:**
```advpl
oClient:SetScopes({"https://mail.google.com/", "openid"})
```

---

### HasError(nEvent, cError)

Verifica se houve erro na última operação. Preenche as variáveis passadas por referência com o código e a descrição do evento registrado na instância.

| Parâmetro | Tipo | Descrição |
|---|---|---|
| `nEvent` | Numeric | Variável que receberá o código do evento registrado |
| `cError` | Character | Variável que receberá a descrição do evento registrado |

**Retorno:** `Logical` — `.T.` se `nEvent` for menor que zero (erro), `.F.` caso contrário.

**Exemplo:**
```advpl
Local nEvt as numeric
Local cMsg as character
If oClient:HasError(nEvt, cMsg)
    ConOut("Erro " + cValToChar(nEvt) + ": " + cMsg)
EndIf
```

---

### ClearEvent()

Limpa o último evento registrado na instância, redefinindo `nEvent` para `0` e `cEventDesc` para vazio. Também chama `ClearError()` da superclasse.

**Exemplo:**
```advpl
oClient:ClearEvent()
```

---

### validEmail()

Valida se o e-mail informado no construtor existe na tabela `SYS_OAUTH_ACCOUNT` e se o provedor vinculado à conta existe na tabela `SYS_OAUTH_PROVIDER`. Em caso de falha, registra o evento de erro correspondente.

**Retorno:** `Logical` — `.T.` se o e-mail e o provedor forem encontrados, `.F.` caso contrário.

**Exemplo:**
```advpl
If oClient:validEmail()
    ConOut("E-mail válido.")
EndIf
```

---

### updateValues()

Atualiza as propriedades internas da instância com base nos dados da conta e do provedor cadastrados. Configura o tipo de autenticação (`oauth2` ou `basic`), URLs, credenciais e o grant type (`authorization_code` ou `client_credentials`). Chamado automaticamente pelo construtor.

**Exemplo:**
```advpl
oClient:updateValues()
```

---

### GetValidToken(lOnlyGet, lCheckMail)

Obtém um token de acesso válido. O comportamento varia conforme o fluxo configurado:

- **`lOnlyGet = .T.`** ou autenticação Basic: retorna o token atual sem validações adicionais.
- **`client_credentials`**: verifica expiração e requisita novo token se necessário.
- **`authorization_code`**: verifica tokens armazenados na tabela, realiza refresh automático quando expirado e atualiza o registro.

| Parâmetro | Tipo | Descrição |
|---|---|---|
| `lOnlyGet` | Logical | Se `.T.`, retorna o token atual sem validações ou requisições adicionais. Padrão: `.F.` |
| `lCheckMail` | Logical | Se `.T.`, valida o e-mail antes de processar o token, evitando chamadas duplicadas. Padrão: `.T.` |

**Retorno:** `Character` — token de acesso válido; string vazia em caso de falha.

**Exemplo:**
```advpl
Local cToken as character
cToken := oClient:GetValidToken()
If !Empty(cToken)
    ConOut("Token obtido: " + cToken)
EndIf
```

---

### Consent()

Realiza o processo de consentimento OAuth. Adiciona o parâmetro `login_hint` às opções de autenticação (caso ainda não esteja presente) e acessa a URL de autorização configurada. Registra evento de erro se a operação falhar.

**Retorno:** `Logical` — `.T.` se o acesso à URL de autorização foi realizado com sucesso, `.F.` em caso de erro prévio ou falha no acesso.

**Exemplo:**
```advpl
If oClient:Consent()
    ConOut("Consentimento realizado com sucesso.")
EndIf
```

---

### SendMail(oMessage)

Realiza o envio de um e-mail utilizando o `TMailManager` configurado pela classe. Executa sequencialmente: conexão SMTP, autenticação (quando o provedor exige) e envio da mensagem. Registra o evento correspondente ao resultado de cada etapa.

| Parâmetro | Tipo | Descrição |
|---|---|---|
| `oMessage` | Object | Instância de `TMailMessage` com a mensagem a ser enviada |

**Retorno:** `Logical` — `.T.` se o e-mail foi enviado com sucesso, `.F.` em caso de falha em qualquer etapa.

**Exemplo:**
```advpl
Local oMsg as object
oMsg := TMailMessage():New()
// ... configuração da mensagem ...
If oClient:SendMail(oMsg)
    ConOut("E-mail enviado com sucesso.")
EndIf
```

---

### GetMailManager(lCheckMail)

Inicializa e configura uma instância de `TMailManager` com base nos dados do provedor e da conta (servidor SMTP, porta, TLS, SSL, timeout). Quando o tipo de autenticação é OAuth2, obtém e aplica o token de acesso via `GetValidToken()`. O objeto retornado **não** está conectado ao SMTP.

| Parâmetro | Tipo | Descrição |
|---|---|---|
| `lCheckMail` | Logical | Se `.T.`, valida o e-mail antes de configurar o gerenciador. Padrão: `.T.` |

**Retorno:** `Object` — instância de `TMailManager` configurada, ou o valor atual do atributo `oMailManager` caso a validação falhe.

**Exemplo:**
```advpl
Local oManager as object
oManager := oClient:GetMailManager()
```

---

### GetMail()

Retorna o endereço de e-mail armazenado no atributo privado `cEmail` da instância.

**Retorno:** `Character` — endereço de e-mail do cliente.

**Exemplo:**
```advpl
ConOut("E-mail configurado: " + oClient:GetMail())
```

---

### IsBasic()

Indica se o tipo de autenticação configurado para a conta é Basic.

**Retorno:** `Logical` — `.T.` se o tipo de autenticação for `"basic"`, `.F.` caso contrário.

**Exemplo:**
```advpl
If oClient:IsBasic()
    ConOut("Autenticação Basic configurada.")
EndIf
```

---

### IsOauth2()

Indica se o tipo de autenticação configurado para a conta é OAuth 2.0.

**Retorno:** `Logical` — `.T.` se o tipo de autenticação for `"oauth2"`, `.F.` caso contrário.

**Exemplo:**
```advpl
If oClient:IsOauth2()
    ConOut("Autenticação OAuth2 configurada.")
EndIf
```

---

### isExpired(nExpireAt, nSecondsNow)

Função estática. Verifica se um token está expirado, aplicando uma margem de antecipação de 10 segundos antes do vencimento para forçar a renovação preventiva.

| Parâmetro | Tipo | Descrição |
|---|---|---|
| `nExpireAt` | Numeric | Timestamp de expiração do token em microssegundos |
| `nSecondsNow` | Numeric | Tempo atual em microssegundos. Padrão: resultado de `Microseconds()` |

**Retorno:** `Logical` — `.T.` se o token estiver expirado ou prestes a expirar (dentro de 10 segundos), `.F.` caso contrário.

**Exemplo:**
```advpl
If isExpired(nTokenExpireAt)
    ConOut("Token expirado, necessário renovar.")
EndIf
```