<?php namespace App\Integrations\Celcoin; use App\Models\CelcoinCustomer; use App\Models\User; use Exception; /** * Serviço de gerenciamento de clientes na Celcoin * Sincroniza dados de usuários do sistema com a Celcoin */ class CelcoinCustomerService { private CelcoinHttpClient $httpClient; private CelcoinAuthService $authService; private int $companyId; private int $gatewaySettingId; public function __construct(int $companyId, int $gatewaySettingId) { $this->companyId = $companyId; $this->gatewaySettingId = $gatewaySettingId; $this->authService = new CelcoinAuthService($companyId, $gatewaySettingId); $this->httpClient = new CelcoinHttpClient($companyId); } /** * Sincroniza um usuário do sistema com a Celcoin */ public function syncCustomer(int $userId): array { try { // Buscar dados do usuário $user = $this->getUserData($userId); if (!$user) { throw new Exception("User not found: {$userId}"); } // Verificar se já existe cliente sincronizado $existingCustomer = $this->getExistingCustomer($userId); if ($existingCustomer) { // Atualizar cliente existente return $this->updateCustomer($existingCustomer, $user); } else { // Criar novo cliente return $this->createCustomer($user); } } catch (Exception $e) { $this->logSyncError('Customer sync failed', $userId, $e->getMessage()); throw new Exception('Failed to sync customer: ' . $e->getMessage()); } } /** * Cria um novo cliente na Celcoin */ public function createCustomer(array $userData): array { try { // Obter token válido $accessToken = $this->authService->getValidAccessToken(); $this->httpClient->setAccessToken($accessToken); // Preparar dados do cliente para a API da Celcoin $customerData = $this->prepareCustomerData($userData); // Fazer requisição para criar cliente $response = $this->httpClient->post('/v5/customers', $customerData); if (!$response['success']) { throw new Exception('Failed to create customer in Celcoin API'); } $celcoinCustomer = $response['data']; // Salvar referência no banco local $this->saveCustomerReference($userData['id'], $celcoinCustomer); // Log de sucesso $this->logSyncSuccess('Customer created', $userData['id'], $celcoinCustomer['id']); return [ 'success' => true, 'customer_id' => $celcoinCustomer['id'], 'action' => 'created' ]; } catch (Exception $e) { $this->logSyncError('Customer creation failed', $userData['id'], $e->getMessage()); throw $e; } } /** * Atualiza um cliente existente na Celcoin */ public function updateCustomer(array $existingCustomer, array $userData): array { try { // Obter token válido $accessToken = $this->authService->getValidAccessToken(); $this->httpClient->setAccessToken($accessToken); // Preparar dados atualizados $customerData = $this->prepareCustomerData($userData); // Fazer requisição para atualizar cliente $response = $this->httpClient->put("/v5/customers/{$existingCustomer['celcoin_customer_id']}", $customerData); if (!$response['success']) { throw new Exception('Failed to update customer in Celcoin API'); } // Atualizar referência local $this->updateCustomerReference($existingCustomer['id'], $response['data']); // Log de sucesso $this->logSyncSuccess('Customer updated', $userData['id'], $existingCustomer['celcoin_customer_id']); return [ 'success' => true, 'customer_id' => $existingCustomer['celcoin_customer_id'], 'action' => 'updated' ]; } catch (Exception $e) { $this->logSyncError('Customer update failed', $userData['id'], $e->getMessage()); throw $e; } } /** * Busca um cliente na Celcoin por ID */ public function getCustomer(string $celcoinCustomerId): ?array { try { $accessToken = $this->authService->getValidAccessToken(); $this->httpClient->setAccessToken($accessToken); $response = $this->httpClient->get("/v5/customers/{$celcoinCustomerId}"); if (!$response['success']) { return null; } return $response['data']; } catch (Exception $e) { $this->logSyncError('Customer fetch failed', 0, $e->getMessage()); return null; } } /** * Lista clientes da empresa */ public function listCustomers(int $page = 1, int $limit = 50): array { try { $accessToken = $this->authService->getValidAccessToken(); $this->httpClient->setAccessToken($accessToken); $params = [ 'page' => $page, 'limit' => $limit ]; $response = $this->httpClient->get('/v5/customers?' . http_build_query($params)); if (!$response['success']) { throw new Exception('Failed to list customers'); } return $response['data']; } catch (Exception $e) { $this->logSyncError('Customer list failed', 0, $e->getMessage()); throw $e; } } /** * Remove um cliente da Celcoin */ public function deleteCustomer(string $celcoinCustomerId): bool { try { $accessToken = $this->authService->getValidAccessToken(); $this->httpClient->setAccessToken($accessToken); $response = $this->httpClient->delete("/v5/customers/{$celcoinCustomerId}"); if ($response['success']) { // Remover referência local $this->removeCustomerReference($celcoinCustomerId); $this->logSyncSuccess('Customer deleted', 0, $celcoinCustomerId); return true; } return false; } catch (Exception $e) { $this->logSyncError('Customer deletion failed', 0, $e->getMessage()); return false; } } /** * Sincroniza múltiplos clientes em lote */ public function syncCustomersBatch(array $userIds): array { $results = [ 'total' => count($userIds), 'successful' => 0, 'failed' => 0, 'errors' => [] ]; foreach ($userIds as $userId) { try { $this->syncCustomer($userId); $results['successful']++; } catch (Exception $e) { $results['failed']++; $results['errors'][] = [ 'user_id' => $userId, 'error' => $e->getMessage() ]; } } return $results; } /** * Busca dados do usuário no sistema */ private function getUserData(int $userId): ?array { $userModel = new User(); $user = $userModel->find($userId); if (!$user) { return null; } // Retornar dados relevantes para a Celcoin return [ 'id' => $user->id, 'name' => $user->name, 'email' => $user->email, 'document' => $user->document ?? null, 'phone' => $user->phone ?? null, 'address' => $user->address ?? null ]; } /** * Verifica se já existe cliente sincronizado */ private function getExistingCustomer(int $userId): ?array { $customerModel = new CelcoinCustomer(); return $customerModel->findByUserId($this->companyId, $userId); } /** * Prepara dados do cliente para envio à Celcoin */ private function prepareCustomerData(array $userData): array { $customerData = [ 'name' => $userData['name'], 'email' => $userData['email'] ]; // Adicionar documento se disponível if (!empty($userData['document'])) { $customerData['document'] = $this->cleanDocument($userData['document']); } // Adicionar telefone se disponível if (!empty($userData['phone'])) { $customerData['phone'] = $this->cleanPhone($userData['phone']); } // Adicionar endereço se disponível if (!empty($userData['address'])) { $customerData['address'] = $userData['address']; } return $customerData; } /** * Salva referência do cliente no banco local */ private function saveCustomerReference(int $userId, array $celcoinCustomer): void { $customerModel = new CelcoinCustomer(); $customerModel->create([ 'company_id' => $this->companyId, 'user_id' => $userId, 'celcoin_customer_id' => $celcoinCustomer['id'], 'document' => $celcoinCustomer['document'] ?? null, 'name' => $celcoinCustomer['name'], 'email' => $celcoinCustomer['email'], 'phone' => $celcoinCustomer['phone'] ?? null, 'address' => $celcoinCustomer['address'] ?? null, 'status' => 'active', 'last_sync' => date('Y-m-d H:i:s') ]); } /** * Atualiza referência do cliente no banco local */ private function updateCustomerReference(int $localCustomerId, array $celcoinCustomer): void { $customerModel = new CelcoinCustomer(); $customerModel->update($localCustomerId, [ 'document' => $celcoinCustomer['document'] ?? null, 'name' => $celcoinCustomer['name'], 'email' => $celcoinCustomer['email'], 'phone' => $celcoinCustomer['phone'] ?? null, 'address' => $celcoinCustomer['address'] ?? null, 'last_sync' => date('Y-m-d H:i:s') ]); } /** * Remove referência do cliente do banco local */ private function removeCustomerReference(string $celcoinCustomerId): void { $customerModel = new CelcoinCustomer(); $customerModel->deleteByCelcoinId($this->companyId, $celcoinCustomerId); } /** * Limpa documento (remove formatação) */ private function cleanDocument(string $document): string { return preg_replace('/[^0-9]/', '', $document); } /** * Limpa telefone (remove formatação) */ private function cleanPhone(string $phone): string { return preg_replace('/[^0-9]/', '', $phone); } /** * Log de sucesso na sincronização */ private function logSyncSuccess(string $action, int $userId, string $celcoinId): void { // Implementar logging adequado error_log("[Celcoin Customer] {$action} - User: {$userId}, Celcoin ID: {$celcoinId}"); } /** * Log de erro na sincronização */ private function logSyncError(string $action, int $userId, string $error): void { // Implementar logging adequado error_log("[Celcoin Customer Error] {$action} - User: {$userId}, Error: {$error}"); } }