notification = model(Notification::class); $this->userNotification = model(UserNotification::class); $this->user = model(User::class); $this->emailService = app(EmailService::class); } /** * GET /api/v1/notifications/active * Get active (non-deleted, non-expired) notifications */ public function activeNotificationsData() { try { $targetGroup = $this->request->getGet('target_group'); $payload = $this->buildActiveNotificationsPayload($targetGroup); return $this->success($payload, 'Active notifications retrieved successfully'); } catch (\Throwable $e) { log_message('error', 'Active notifications data error: ' . $e->getMessage()); return $this->respondError('Failed to retrieve active notifications', Response::HTTP_INTERNAL_SERVER_ERROR); } } /** * GET /api/v1/notifications/deleted * Get soft-deleted notifications */ public function deletedNotificationsData() { try { $payload = $this->buildDeletedNotificationsPayload(); return $this->success($payload, 'Deleted notifications retrieved successfully'); } catch (\Throwable $e) { log_message('error', 'Deleted notifications data error: ' . $e->getMessage()); return $this->respondError('Failed to retrieve deleted notifications', Response::HTTP_INTERNAL_SERVER_ERROR); } } /** * POST /api/v1/notifications/send * Create and send notifications to a target group */ public function send() { $user = $this->getCurrentUser(); if (!$user) { return $this->respondError('Authentication required', Response::HTTP_UNAUTHORIZED); } $payload = $this->payloadData(); $title = trim((string) ($payload['title'] ?? '')); $message = trim((string) ($payload['message'] ?? '')); $group = trim((string) ($payload['target_group'] ?? '')); $channels = (array) ($payload['channels'] ?? []); if (empty($title) || empty($message) || empty($group) || empty($channels)) { return $this->respondError('Title, message, target_group, and channels are required', Response::HTTP_BAD_REQUEST); } try { // Create notification $notifId = $this->notification->insert([ 'title' => $title, 'message' => $message, 'target_group' => $group, 'delivery_channels' => implode(',', $channels), 'created_at' => utc_now(), ], true); if (!$notifId) { return $this->respondError('Failed to create notification', Response::HTTP_INTERNAL_SERVER_ERROR); } // Get users by role (target_group) $users = $this->user->getUsersByRole($group); $sentCount = 0; $emailCount = 0; $smsCount = 0; foreach ($users as $user) { // Create user notification record $this->userNotification->insert([ 'notification_id' => $notifId, 'user_id' => (int) $user['id'], 'is_read' => 0, ]); // Send via email if requested if (in_array('email', $channels) && !empty($user['email'])) { try { $this->sendEmail($user['email'], $title, $message); $emailCount++; } catch (\Throwable $e) { log_message('error', 'Failed to send email to ' . $user['email'] . ': ' . $e->getMessage()); } } // Send via SMS if requested if (in_array('sms', $channels) && !empty($user['cellphone'])) { try { $this->sendSMS($user['cellphone'], $message); $smsCount++; } catch (\Throwable $e) { log_message('error', 'Failed to send SMS to ' . $user['cellphone'] . ': ' . $e->getMessage()); } } $sentCount++; } return $this->success([ 'notification_id' => $notifId, 'users_notified' => $sentCount, 'emails_sent' => $emailCount, 'sms_sent' => $smsCount, ], 'Notification sent successfully'); } catch (\Throwable $e) { log_message('error', 'Notification send error: ' . $e->getMessage()); return $this->respondError('Failed to send notification: ' . $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR); } } /** * POST /api/v1/notifications/{id}/restore * Restore a soft-deleted notification */ public function restore($id) { try { $id = (int) $id; // Check if notification exists and is deleted $notification = $this->notification->withDeleted()->find($id); if (!$notification) { return $this->respondError('Notification not found', Response::HTTP_NOT_FOUND); } $restored = $this->notification->restoreNotification($id); // Check if update was successful (update returns affected rows or false) if ($restored !== false) { return $this->success([ 'id' => $id, ], 'Notification restored successfully'); } return $this->respondError('Failed to restore notification', Response::HTTP_BAD_REQUEST); } catch (\Throwable $e) { log_message('error', 'Notification restore error: ' . $e->getMessage()); return $this->respondError('Failed to restore notification: ' . $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR); } } /** * Build active notifications payload */ private function buildActiveNotificationsPayload(?string $targetGroup): array { $targetGroup = $targetGroup !== null ? trim($targetGroup) : null; if ($targetGroup === '') { $targetGroup = null; } $rows = $this->notification->getActiveNotifications($targetGroup); if (!is_array($rows)) { $rows = []; } $now = time(); $notifications = array_map(static function ($row) use ($now) { if (!is_array($row)) { return []; } $expiresAt = $row['expires_at'] ?? null; $expiryTs = $expiresAt ? strtotime((string) $expiresAt) : false; $isExpired = $expiryTs !== false && $expiryTs <= $now; return [ 'id' => $row['id'] ?? null, 'title' => $row['title'] ?? null, 'message' => $row['message'] ?? null, 'priority' => $row['priority'] ?? null, 'scheduled_at' => $row['scheduled_at'] ?? null, 'expires_at' => $expiresAt, 'created_at' => $row['created_at'] ?? null, 'target_group' => $row['target_group'] ?? null, 'isExpired' => $isExpired, ]; }, $rows); return [ 'notifications' => $notifications, ]; } /** * Build deleted notifications payload */ private function buildDeletedNotificationsPayload(): array { $rows = $this->notification->getDeletedNotifications(); if (!is_array($rows)) { $rows = []; } $notifications = array_map(static function ($row) { if (!is_array($row)) { return []; } return [ 'id' => $row['id'] ?? null, 'title' => $row['title'] ?? null, 'message' => $row['message'] ?? null, 'priority' => $row['priority'] ?? null, 'scheduled_at' => $row['scheduled_at'] ?? null, 'expires_at' => $row['expires_at'] ?? null, 'deleted_at' => $row['deleted_at'] ?? null, ]; }, $rows); return [ 'notifications' => $notifications, ]; } /** * Send email notification */ protected function sendEmail(string $to, string $subject, string $message): void { try { $this->emailService->setTo($to); $this->emailService->setSubject($subject); $this->emailService->setMessage($message); $this->emailService->send(); } catch (\Throwable $e) { log_message('error', 'Email send error: ' . $e->getMessage()); throw $e; } } /** * Send SMS notification (placeholder - logs for now) */ protected function sendSMS(string $phone, string $message): void { log_message('info', "SMS to {$phone}: {$message}"); // TODO: Implement actual SMS sending via SendSMSController or SMS service } }