where('item_id', $filters['item_id']); } // Filter by user ID if (isset($filters['user_id'])) { $query->where('user_id', $filters['user_id']); } // Filter by date range if (isset($filters['date_from'])) { $query->where('started_at', '>=', $filters['date_from']); } if (isset($filters['date_to'])) { $query->where('started_at', '<=', $filters['date_to']); } // Filter by IP address if (isset($filters['ip_address'])) { $query->where('ip_address', $filters['ip_address']); } return $query->orderBy('started_at', 'desc')->get(); } /** * Get product visits with pagination */ public function getPaginated(array $filters = [], int $perPage = 20): LengthAwarePaginator { $query = AnalyticsProductVisit::query(); // Apply same filters as getAll method if (isset($filters['item_id'])) { $query->where('item_id', $filters['item_id']); } if (isset($filters['user_id'])) { $query->where('user_id', $filters['user_id']); } if (isset($filters['date_from'])) { $query->where('started_at', '>=', $filters['date_from']); } if (isset($filters['date_to'])) { $query->where('started_at', '<=', $filters['date_to']); } return $query->orderBy('started_at', 'desc') ->paginate($perPage); } /** * Create a new product visit record */ public function create(array $data): AnalyticsProductVisit { return AnalyticsProductVisit::create($data); } /** * Update existing product visit */ public function update(int $id, array $data): bool { $visit = AnalyticsProductVisit::find($id); if (!$visit) { return false; } return $visit->update($data); } /** * Delete a product visit record */ public function delete(int $id): bool { $visit = AnalyticsProductVisit::find($id); if (!$visit) { return false; } return $visit->delete(); } /** * Get visit statistics */ public function getStatistics(array $filters = []): array { $query = AnalyticsProductVisit::query(); // Apply date filters if (isset($filters['date_from'])) { $query->where('started_at', '>=', $filters['date_from']); } if (isset($filters['date_to'])) { $query->where('started_at', '<=', $filters['date_to']); } $totalVisits = $query->count(); $uniqueVisitors = $query->distinct('user_id')->count('user_id'); $averageDuration = $query->avg('duration_seconds'); $totalDuration = $query->sum('duration_seconds'); return [ 'total_visits' => $totalVisits, 'unique_visitors' => $uniqueVisitors, 'average_duration_seconds' => round($averageDuration, 2), 'total_duration_seconds' => $totalDuration, 'average_duration_formatted' => $this->formatDuration($averageDuration), 'total_duration_formatted' => $this->formatDuration($totalDuration), ]; } /** * Get most visited products */ public function getMostVisitedProducts(int $limit = 10): array { return AnalyticsProductVisit::query() ->selectRaw('item_id, COUNT(*) as visit_count, AVG(duration_seconds) as avg_duration') ->groupBy('item_id') ->orderBy('visit_count', 'desc') ->limit($limit) ->get() ->toArray(); } /** * Get visits by device type */ public function getVisitsByDeviceType(array $filters = []): array { $query = AnalyticsProductVisit::query(); if (isset($filters['date_from'])) { $query->where('started_at', '>=', $filters['date_from']); } if (isset($filters['date_to'])) { $query->where('started_at', '<=', $filters['date_to']); } return $query->selectRaw('device_type, COUNT(*) as count') ->groupBy('device_type') ->orderBy('count', 'desc') ->get() ->toArray(); } /** * Get daily visit statistics */ public function getDailyStatistics(array $filters = []): array { $query = AnalyticsProductVisit::query(); if (isset($filters['date_from'])) { $query->where('started_at', '>=', $filters['date_from']); } if (isset($filters['date_to'])) { $query->where('started_at', '<=', $filters['date_to']); } return $query->selectRaw('DATE(started_at) as date, COUNT(*) as visits, COUNT(DISTINCT user_id) as unique_visitors') ->groupBy('date') ->orderBy('date', 'desc') ->get() ->toArray(); } /** * Format duration in human readable format */ private function formatDuration(float $seconds): string { if ($seconds < 60) { return round($seconds) . 's'; } if ($seconds < 3600) { $minutes = floor($seconds / 60); $remainingSeconds = $seconds % 60; return $minutes . 'm ' . round($remainingSeconds) . 's'; } $hours = floor($seconds / 3600); $remainingSeconds = $seconds % 3600; $minutes = floor($remainingSeconds / 60); $remainingSeconds = $remainingSeconds % 60; return $hours . 'h ' . $minutes . 'm ' . round($remainingSeconds) . 's'; } /** * Get product visit by ID */ public function findById(int $id): ?AnalyticsProductVisit { return AnalyticsProductVisit::find($id); } /** * Get visits by session ID */ public function getBySessionId(string $sessionId): Collection { return AnalyticsProductVisit::where('session_id', $sessionId) ->orderBy('started_at', 'desc') ->get(); } /** * Bulk insert visits */ public function bulkInsert(array $visits): bool { try { AnalyticsProductVisit::insert($visits); return true; } catch (\Exception $e) { return false; } } }