<?php

// 1. Enhanced Activity Log Service

namespace App\Services;

use Carbon\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Spatie\Activitylog\Models\Activity;

class PresenceService
{
    public const PRESENCE_ACTIVITY = 'presence_update';
    public const ONLINE_THRESHOLD_MINUTES = 5;

    public function updatePresence($user = null, $guard = null)
    {
        $user = $user ?? Auth::user();
        $guard = $guard ?? Auth::getDefaultDriver();

        if (!$user) {
            return;
        }

        // Log activity using Spatie
        activity(self::PRESENCE_ACTIVITY)
            ->performedOn($user)
            ->causedBy($user)
            ->withProperties([
                'guard' => $guard,
                'ip_address' => request()->ip(),
                'user_agent' => request()->userAgent(),
                'timestamp' => now(),
                'status' => 'online',
            ])
            ->event('updated')
            ->log('User online');

        // Cache for quick access
        $cacheKey = "presence_{$guard}_{$user->id}";
        Cache::put($cacheKey, [
            'user_id' => $user->id,
            'user_type' => get_class($user),
            'guard' => $guard,
            'name' => $user->name,
            'avatar' => $user->avatar ?? null,
            'last_seen' => now(),
            'status' => 'online',
        ], now()->addMinutes(self::ONLINE_THRESHOLD_MINUTES + 2));

        // Broadcast presence update
        broadcast(new \App\Events\UserPresenceUpdated($user, $guard, 'online'));

        // Clear cache for online users to force refresh
        Cache::forget("online_users_{$guard}_" . self::ONLINE_THRESHOLD_MINUTES);

        // Cleanup old presence records for this user
        $this->cleanupUserPresenceRecords($user, $guard);
    }

    public function setUserOffline($user, $guard = 'web')
    {
        if (!$user) {
            return;
        }

        // Log offline activity
        activity(self::PRESENCE_ACTIVITY)
            ->performedOn($user)
            ->causedBy($user)
            ->withProperties([
                'guard' => $guard,
                'status' => 'offline',
                'timestamp' => now(),
            ])
            ->log('User offline');

        // Remove from cache
        $cacheKey = "presence_{$guard}_{$user->id}";
        Cache::forget($cacheKey);

        // Broadcast offline status
        broadcast(new \App\Events\UserPresenceUpdated($user, $guard, 'offline'));

        // Clear online users cache
        Cache::forget("online_users_{$guard}_" . self::ONLINE_THRESHOLD_MINUTES);

        // Don't cleanup on offline - preserve presence history
    }

    public function getOnlineUsers($guard = 'web', $minutes = null)
    {
        $minutes = $minutes ?? self::ONLINE_THRESHOLD_MINUTES;
        $cacheKey = "online_users_{$guard}_{$minutes}";

        return Cache::remember($cacheKey, 30, function () use ($guard, $minutes) {
            try {
                // Simple and reliable database query
                $activities = Activity::where('log_name', self::PRESENCE_ACTIVITY)
                    ->where('properties->guard', $guard)
                    ->where('created_at', '>=', now()->subMinutes($minutes))
                    ->with('subject')
                    ->latest()
                    ->get();

                // Group by user and get the latest activity for each
                $userActivities = $activities->groupBy('subject_id')->map(function ($userActivities) {
                    return $userActivities->first(); // Get the most recent activity
                });

                // Filter out offline users and map to user data
                $onlineUsers = $userActivities->map(function ($activity) {
                    $user = $activity->subject;
                    if (!$user) {
                        return null;
                    }

                    // Skip if latest activity is "offline"
                    $properties = is_string($activity->properties) ? json_decode($activity->properties, true) : $activity->properties;
                    if (isset($properties['status']) && $properties['status'] === 'offline') {
                        return null;
                    }

                    return [
                        'id' => $user->id,
                        'name' => $user->name,
                        'avatar' => $user->avatar ?? null,
                        'guard' => $properties['guard'] ?? $guard,
                        'last_seen' => $activity->created_at,
                        'user_type' => $activity->subject_type,
                        'status' => $properties['status'] ?? 'online',
                    ];
                })->filter()->values();

                return $onlineUsers;
            } catch (\Exception $e) {
                // Return empty collection on error
                \Log::error('PresenceService getOnlineUsers error: ' . $e->getMessage());
                return collect([]);
            }
        });
    }

    public function isUserOnline($user, $guard = 'web', $minutes = null)
    {
        $minutes = $minutes ?? self::ONLINE_THRESHOLD_MINUTES;
        $cacheKey = "presence_{$guard}_{$user->id}";

        // Check cache first, but only for online status
        $cachedData = Cache::get($cacheKey);
        if ($cachedData && isset($cachedData['status']) && $cachedData['status'] === 'online') {
            return true;
        }

        // Get the most recent presence activity for this user
        $latestActivity = Activity::where('log_name', self::PRESENCE_ACTIVITY)
            ->where('subject_id', $user->id)
            ->where('subject_type', get_class($user))
            ->where('properties->guard', $guard)
            ->where('created_at', '>=', now()->subMinutes($minutes))
            ->latest()
            ->first();

        if (!$latestActivity) {
            return false;
        }

        // Check if the latest activity is "offline"
        $properties = is_string($latestActivity->properties)
            ? json_decode($latestActivity->properties, true)
            : $latestActivity->properties;

        return isset($properties['status']) && $properties['status'] === 'online';
    }

    public function getUserLastSeen($user, $guard = 'web')
    {
        $activity = Activity::where('log_name', self::PRESENCE_ACTIVITY)
            ->where('subject_id', $user->id)
            ->where('subject_type', get_class($user))
            ->where('properties->guard', $guard)
            ->latest()
            ->first();

        return $activity ? $activity->created_at : null;
    }

    public function getPresenceStats($guard = 'web')
    {
        $onlineUsers = $this->getOnlineUsers($guard);

        return [
            'online_count' => $onlineUsers->count(),
            'online_users' => $onlineUsers,
            'guard' => $guard,
            'updated_at' => now(),
        ];
    }

    /**
     * Clean up old presence records for a specific user, keeping only the latest, as defined in config
     */
    protected function cleanupUserPresenceRecords($user, $guard = 'web')
    {
        $keepCount = timebank_config('presence_settings.keep_last_presence_updates', timebank_config('presence_settings.keep_last_presence_updates'));

        $userActivities = Activity::where('log_name', self::PRESENCE_ACTIVITY)
            ->where('causer_id', $user->id)
            ->where('causer_type', get_class($user))
            ->where('properties->guard', $guard)
            ->orderBy('created_at', 'desc')
            ->get();

        if ($userActivities->count() > $keepCount) {
            $toDelete = $userActivities->skip($keepCount)->pluck('id');
            Activity::whereIn('id', $toDelete)->delete();
        }
    }
}
